How to get convex hull using ddply?
plyr, r
Solution
Two hints:
- Use the `chull` function in base R to compute the convex hull.
- Use `dlply` to store the resulting `chull` in a list, rather than a data frame
Then your code turns to:
x <- dlply(df, .(id), function(piece)piece[chull(piece$X, piece$Y), -3])
plot(Y~X, df)
lapply(x, polygon)
Which produces this plot:
If you want to plot this in `ggplot` it's even easier, but use `ddply`:
x <- ddply(df, .(id), function(piece)piece[chull(piece$X, piece$Y), ])
ggplot(x, aes(X, Y, group=id)) + geom_polygon(fill="cyan", colour="blue") + geom_line()
Problem
I am following this example to create polygons to plot using `ggplot` I am able to follow that example and create separate convex hulls if my data is subsetted; however, when I try to apply `ddply` as I have a grouping variable I am unable to. Here's the code from the example with a added grouping variable : ``` library(grDevices) # load grDevices package df <- data.frame(X = c(-62, -40, 9, 13, 26, 27, 27), Y = c( 7, -14, 10, 9, -8, -16, 12), id = c(1, 1, 1, 2, 2, 3, 3)) con.hull.pos <- ddply(df, .(id), summarize, hullpos = chull(X, Y)) # get convex hull positions by each ID ``` Now, to get a complete polygon for each ID, we need to get all the rows by each ID as given in `con.hull.pos` but we also need to add the first row of each group. ``` df[ddply(con.hull.pos, .(id), function(x) x[1, ])$hullpos, ] # first row of position df[con.hull.pos$hullpos ,] ## all rows of position rbind(df[con.hull.pos$hullpos ,] , df[ddply(con.hull.pos, .(id), function(x) x[1, ])$hullpos, ]) ``` and here my code fails as the first row using ddply is not the same as first row from the convex hull for an ID. Thus, the polygon is not complete. Can anyone please help me in applying the given example by grouping by a variable. When subsetting manually, this code works as it creates three separate polygons covering three id areas ``` id1_df <- subset(df, id==1) id1_con.hull.pos <- chull(id1_df$X, id1_df$Y) id2_df <- subset(df, id==2) id2_con.hull.pos <- chull(id2_df$X, id2_df$Y) id3_df <- subset(df, id==3) id3_con.hull.pos <- chull(id3_df$X, id3_df$Y) id1_con.hull <- rbind(id1_df[id1_con.hull.pos,], id1_df [id1_con.hull.pos[1],]) id2_con.hull <- rbind(id2_df [id2_con.hull.pos ,], id2_df [id2_con.hull.pos [1],]) id3_con.hull <- rbind(id3_df [id3_con.hull.pos,], id3_df [id3_con.hull.pos[1],]) poly_borders <- rbind(id1_con.hull, id2_con.hull, id3_con.hull) plot(Y ~ X, data = df) # plot data lines(poly_borders) # add lines for convex hull ```