如何解决ggplot2 geom_density2d 停止正常工作
请参阅下面的示例代码,它输出链接的图像 (link to image)。
在这个包含 3 组的数据集中,当我一次绘制一组时,一切正常。但是当我将所有 3 个组绘制在一起(右下图)时,绿色和蓝色组的密度线不正确,正如您通过比较右上图与右下图以及左下图与右下图所见情节(分别)。
这个问题最近开始出现,因为过去一切正常。我不确定是什么导致了这个问题,所以我从我的 MacBook Pro(macOS Catalina 10.15.6)中卸载了 R,然后重新安装了 R(4.0.5)和 ggplot2,但问题仍然存在。你能帮忙吗?谢谢。
library(gridExtra); library(ggplot2)
dat <- read.csv(url("https://github.com/tidyverse/ggplot2/files/6426291/test.csv"))
p1 <- ggplot(dat[dat$Type=="type1",],aes(x=dim1,y=dim2,col=Type))+geom_density2d()+scale_color_manual(values="#F8766D")+theme_classic()+theme(legend.position="top")+scale_x_continuous(limits=c(-50,50))+scale_y_continuous(limits=c(-50,50))
p2 <- ggplot(dat[dat$Type=="type2",col=Type))+geom_density2d()+scale_color_manual(values="#00BA38")+theme_classic()+theme(legend.position="top")+scale_x_continuous(limits=c(-50,50))
p3 <- ggplot(dat[dat$Type=="type3",col=Type))+geom_density2d()+scale_color_manual(values="#619CFF")+theme_classic()+theme(legend.position="top")+scale_x_continuous(limits=c(-50,50))
p4 <- ggplot(dat,col=Type))+geom_density2d()+theme_classic()+theme(legend.position="top")+scale_x_continuous(limits=c(-50,50))
grid.arrange(p1,p2,p3,p4,nrow=2)
解决方法
来自 Claus Wilke (GitHub) 的解决方案:用 geom_density2d(contour_var="ndensity") 替换 geom_density2d()
,geom_density2d
工作正常。它只是没有按照你想要的方式工作。您的问题是由于您允许 geom_density2d
自动计算轮廓的位置,并且您的数据在按 Type
分组时具有不同的范围。您可以通过以下方式查看:
dat %>%
group_by(Type) %>%
summarise(across(everything(),.fns=list(min=min,max=max,mean=mean)),.groups="drop")
# A tibble: 3 x 7
Type dim1_min dim1_max dim1_mean dim2_min dim2_max dim2_mean
* <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 type1 -16.2 35.0 7.31 -23.8 41.1 29.2
2 type2 -30.2 43.6 23.5 -11.3 43.3 8.43
3 type3 -39.2 39.6 -15.4 -41.4 30.8 -15.6
这意味着由 geom_density2d()
标记的密度级别在类型级别(在单个图中)和整个数据集之间是不同的。解决方案是强制 geom_density2d()
使用您想要的轮廓。一旦您知道要使用的轮廓,就可以使用 breaks
参数完成此操作。
找出原始图中使用的轮廓有点难看,但可以做到:
unique(ggplot_build(p1)$data[[1]]$level)
[1] 0.0005 0.0010 0.0015 0.0020 0.0025 0.0030 0.0035 0.0040 0.0045
unique(ggplot_build(p2)$data[[1]]$level)
[1] 0.0002 0.0004 0.0006 0.0008 0.0010 0.0012 0.0014
unique(ggplot_build(p3)$data[[1]]$level)
[1] 1e-04 2e-04 3e-04 4e-04 5e-04 6e-04 7e-04 8e-04
unique(ggplot_build(p4)$data[[1]]$level)
[1] 0.0005 0.0010 0.0015 0.0020 0.0025 0.0030 0.0035 0.0040 0.0045
简而言之,ggplot_build
允许您检查 ggplot
对象下的数据。在这里,我打印了四个绘图中每一个的独特轮廓级别。
我们可以通过将每个图中使用的轮廓整理成单个向量来强制 geom_density2d()
在整个图中使用我们想要的轮廓。假设 b1
、b2
和 b3
是上述前三个调用的结果。然后设置
b <- c(b1,b2,b3)
并使用例如
p1 <- dat %>%
filter(Type == "type1") %>%
ggplot(Type=="type1",aes(x=dim1,y=dim2,col=Type)) +
geom_density2d(breaks=b) +
scale_color_manual(values="#F8766D") +
theme_classic() +
theme(legend.position="top") +
coord_cartesian(xlim=c(-50,50),ylim=c(-50,50))
和
p4 <- data %>%
ggplot(dat,col=Type)) +
geom_density2d(breaks=b) +
theme_classic() +
theme(legend.position="top") +
coord_cartesian(xlim=c(-50,50))
这样你的最终组合图就变成了:
一些额外的评论:
- 这些新图与您的原图不同的原因是您现在在每个图中使用了不同的等高线级别。
- 我已经使用您的原始图来定义等高线级别。显然,您不会在最终的工作代码中这样做 - 您可以使用任何您喜欢的级别:只需使用
breaks
参数将它们传递给每个绘图。 - 我已经修改了您创建
p1
的代码,以使用更常用的语法,但它的作用与原始语法完全相同。就我个人而言,我发现标准语法更易于阅读。 - 我认为您应该在调用
coord_cartesian()
函数时使用limits
来设置轴限制,而不是scale_xxxx
。原因是coord_cartesian
使用整个数据集来创建绘图,然后将输出“缩放”到请求的视口。limits
另一方面,在仅使用视口中的点创建绘图之前过滤数据集。当绘图涉及插值或创建汇总统计时,这可能会产生意想不到的后果。根据我的经验,coord-cartesian
几乎总是给出“正确”的输出。 - 以后,请格式化您的代码,以便于阅读。除非查看者向右滚动,否则您的代码的重要功能在这篇文章中是不可见的。帮助我们为您提供帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。