Hey,
I’ve decided to do a quick post on how to add a convex hull to a x-y scatterplot in R. This a handy way of visualizing data if you have multiple dataset on one plot. If you google “convex hull in R stat”, you will find many existing packages that have functions to do this, but as always, I like to use base functions as much as possible to do the dirty work, and resort to contributed packages as needed. Lets go!
First, I’ll introduce the function I created to make the convex hull, Plot_ConvexHull.R. We utilize the base function “chull()”, which takes the x,y coordinates of your data and outputs a vector (hpts variable) of integers that indicate the points in your dataset that comprise the convex hull around your data (see ?chull for more details). You will see that I append hpts[1] to the end of the hpts so that the convex hull creates a closed circle around the data points. Finally I use the base function lines to draw the convex hull using the x,y coordinates stored in hpts. Pretty simple:
### Plotting function to plot convex hulls ### Filename: Plot_ConvexHull.R ### Notes: ############################################################################ # INPUTS: # xcoords: x-coordinates of point data # ycoords: y-coordinates of point data # lcolor: line color # OUTPUTS: # convex hull around data points in a particular color (specified by lcolor) # FUNCTION: Plot_ConvexHull<-function(xcoord, ycoord, lcolor){ hpts <- chull(x = xcoord, y = ycoord) hpts <- c(hpts, hpts[1]) lines(xcoord[hpts], ycoord[hpts], col = lcolor) } # END OF FUNCTION
Now, let’s do a simple example using Plot_ConvexHull.R:
#Tell R where your function is located (this will be unique to your file directory) source("/home/location_of_R_code/Plot_ConvexHull.R") # Create 3 sets of random data to plot convex hull around x1 <- rnorm(100, 0.8, 0.3) y1 <- rnorm(100, 0.8, 0.3) x2 <- rnorm(100, 0.2, 0.3) y2 <- rnorm(100, 0.2, 0.3) x3 <- rnorm(100, 1.4, 0.3) y3 <- rnorm(100, 1.4, 0.3) # get max and min of all x and y data for nice plotting xrange <- range(c(x1, x2, x3)) yrange <- range(c(y1, y2, y3)) # Plot it up! par(tck = 0.02, mgp = c(1.7, 0.3, 0)) plot(x1, y1, type = "p", pch = 1, col = "black", xlim = c(xrange), ylim = c(yrange)) Plot_ConvexHull(xcoord = x1, ycoord = y1, lcolor = "black") points(x2, y2, type = "p", pch = 1, col = "green") Plot_ConvexHull(xcoord = x2, ycoord = y2, lcolor = "green") points(x3, y3, type = "p", pch = 1, col = "magenta") Plot_ConvexHull(xcoord = x3, ycoord = y3, lcolor = "magenta")
Oh yeah, happy new year!!!
Awesome
–TEM
great post
Thanks!
can you add a formula to calculate the area within the convex hull
Interesting question. I have some ideas on how to do this, possibly with the “sp” package. I’ll see I can get it working, and I may make it into a new post! Cheers.
UPDATE: I just added a new post on how to calculate the area of a convex hull. Let me know if this helps.
Pingback: Calculating the area of a convex hull | Chit Chat R
Hey Thanks. Nice post.
Also could you add on how to later have a check if a point lies inside or not.
Thanks! My most recent post used the “sp” package to get the area of the convex hull, and this package should have a function for checking whether points are inside polygons. I will try and get a post up soon regarding your question, but in the meantime take a look at the sp package and see if it can help you out.
You can do something like:
point.in.polygon(2, 2, chull.poly@coords[,1], chull.poly@coords[,2])
Many thanks!!!!!!!!