如何使用ddply获取凸包?

3

我正在按照这个示例创建多边形以使用ggplot绘制。如果我的数据是子集,我能够按照那个示例创建单独的凸包;然而,当我尝试应用ddply时,由于有一个分组变量,我无法操作。这是来自该示例的代码,其中添加了一个分组变量:

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

现在,为了得到每个ID的完整多边形,我们需要获取每个ID的所有行,如con.hull.pos所示,但我们还需要添加每个组的第一行。
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, ])

我的代码在使用ddply时失败了,因为第一行与ID的凸包的第一行不同。 因此,多边形不完整。 请问有人可以帮我通过按变量分组来应用给定的示例吗?

手动进行子集处理时,此代码有效,因为它创建了三个涵盖三个id区域的单独多边形。

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
1个回答

4

两个提示:

  1. 使用R语言的基础函数chull计算凸包。
  2. 使用dlply将结果存储在一个列表中,而不是数据框。

然后你的代码变成了:

x <- dlply(df, .(id), function(piece)piece[chull(piece$X, piece$Y), -3])

plot(Y~X, df)
lapply(x, polygon)

这将产生以下图表:

enter image description here


如果你想在ggplot中绘制它,使用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()

enter image description here


哦,这就很接近了。谢谢Andrie。我看到多边形实际上会尝试在现有的图表上绘制。我们如何将多边形值存储在数据框中?或者我们如何使用ggplot绘制多边形? - karlos
添加了 ggplot 代码。现在更加简单了,只需要两行代码。 - Andrie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接