我在这里找到了一个使用ggplot和ddply绘制凸包形状的好例子: Drawing outlines around multiple geom_point groups with ggplot
我以为我会尝试类似的东西 - 创建像Ashby Diagram这样的东西 - 用data.table包来练习:
test<-function()
{
library(data.table)
library(ggplot2)
set.seed(1)
这里我定义了一个简单的表:
dt<-data.table(xdata=runif(15),ydata=runif(15),level=rep(c("a","b","c"),each=5),key="level")
然后我按级别定义船体位置:
hulls<-dt[,as.integer(chull(.SD)),by=level]
setnames(hulls,"V1","hcol")
所以我的想法是将船体与dt合并,这样我最终可以操纵船体以获得ggplot的正确形式(如下所示):
ashby<-ggplot(dt,aes(x=xdata,y=ydata,color=level))+
geom_point()+
geom_line()+
geom_polygon(data=hulls,aes(fill=level))
}
但似乎无论如何我尝试合并外壳和dt,我都会收到错误。例如,merge(hulls,dt)会产生错误,如脚注1 所示。
这似乎应该很简单,我确信我只是遗漏了一些明显的东西。任何关于类似帖子的方向或关于如何为ggplot准备船体的想法都非常感谢。或者如果您认为最好坚持采用ddply方法,请告诉我。
不受欢迎的输出示例:
test<-function(){
library(data.table)
library(ggplot2)
dt<-data.table(xdata=runif(15),ydata=runif(15),level=rep(c("a","b","c"),each=5),key="level")
set.seed(1)
hulls<-dt[,as.integer(chull(.SD)),by=level]
setnames(hulls,"V1","hcol")
setkey(dt, 'level') #setting the key seems unneeded
setkey(hulls, 'level')
hulls<-hulls[dt, allow.cartesian = TRUE]
ggplot(dt,aes(x=xdata,y=ydata,color=level))+
geom_point()+
geom_polygon(data=hulls,aes(fill=level))
}
导致一堆交错的多边形:
脚注1:
vecseq中的错误(f __,len __,if(allow.cartesian)否则为NULL as.integer(max(nrow(x),: Join结果为60行;超过15 = MAX(nrow(x)中,nrow(I))。检查i中的重复键值 它一遍又一遍地加入x中的同一组。如果那没关系, 尝试包括
j
并删除by
(by-without-by)以便j运行 每组避免大量分配。如果你确定你想 继续,用allow.cartesian = TRUE重新运行。否则,请搜索 FAQ,Wiki,Stack Overflow和datatable-help中的此错误消息 建议。
答案 0 :(得分:8)
这是你想要做的。生成一些随机数据:
library(ggplot2)
library(data.table)
# You have to set the seed _before_ you generate random data, not after
set.seed(1)
dt <- data.table(xdata=runif(15), ydata=runif(15), level=rep(c("a","b","c"), each=5),
key="level")
这就是魔术发生的地方:
hulls <- dt[, .SD[chull(xdata, ydata)], by = level]
绘制结果:
ggplot(dt,aes(x=xdata,y=ydata,color=level)) +
geom_point() +
geom_polygon(data = hulls,aes(fill=level,alpha = 0.5))
产生
它起作用,因为chull
返回需要从数据中选择以形成凸包的索引向量。然后,我们使用.SD[...]
对每个单独的数据框进行分组,data.table
将level
加在一起。