使用stat_density_2d绘制的二维密度图异常问题求助
解决stat_density_2d边缘截断与空白区域问题
从你的数据和代码来看,图表出现的两个问题原因不同,我们分别来解决:
1. 边缘截断问题
边缘截断是因为coord_cartesian强制裁剪了绘图范围,但stat_density_2d生成的多边形是基于整个数据集的密度估计范围绘制的,超出coord_cartesian设定的区域就会被直接截断。这里有两种可行的解决方法:
方法一:让密度估计范围适配绘图边界
手动指定stat_density_2d的密度估计范围,和你coord_cartesian设定的范围保持一致,这样生成的多边形就不会超出裁剪区域:
ggplot(data=test_data,aes(x = X206.204 , y = X207.204))+ stat_density_2d(geom="polygon",n=800,bins=20, aes(fill = ..level.., alpha = ..level..), # 手动对齐密度估计范围与绘图边界 xlim = c(17,19.6), ylim = c(15.4, 15.9)) + geom_point(color="red")+ labs( x = expression({}^206*"Pb/"*{}^204*"Pb"), y = expression({}^207*"Pb/"*{}^204*"Pb") )+ theme_bw() + theme(panel.grid = element_blank(), axis.text.x = element_text(margin = margin(t = 5, unit = "pt")), axis.text=element_text(size=18), axis.title = element_text(size=22), legend.position="none")+ scale_fill_gradient(low = "cyan1",high = "cyan4")+ scale_x_continuous(breaks = seq(17, 19.6, by = 0.2))+ scale_y_continuous(breaks = seq(15.4, 15.9, by = 0.1))+ coord_cartesian(xlim = c(17,19.6),ylim=c(15.4, 15.9))
方法二:用scale_x/y_continuous替代coord_cartesian
coord_cartesian是硬裁剪(先绘图再切边界),而scale_x/y_continuous的limits参数是先过滤数据再计算密度,生成的多边形自然不会超出绘图范围:
ggplot(data=test_data,aes(x = X206.204 , y = X207.204))+ stat_density_2d(geom="polygon",n=800,bins=20, aes(fill = ..level.., alpha = ..level..)) + geom_point(color="red")+ labs( x = expression({}^206*"Pb/"*{}^204*"Pb"), y = expression({}^207*"Pb/"*{}^204*"Pb") )+ theme_bw() + theme(panel.grid = element_blank(), axis.text.x = element_text(margin = margin(t = 5, unit = "pt")), axis.text=element_text(size=18), axis.title = element_text(size=22), legend.position="none")+ scale_fill_gradient(low = "cyan1",high = "cyan4")+ # 用limits参数替代coord_cartesian的硬裁剪 scale_x_continuous(breaks = seq(17, 19.6, by = 0.2), limits = c(17,19.6))+ scale_y_continuous(breaks = seq(15.4, 15.9, by = 0.1), limits = c(15.4, 15.9))
2. 中间大片无数据区域问题
观察你的数据分布,能明显看到几个独立的聚类(比如x≈17、x≈17.9、x≈18.3-18.7的分组),这些分组之间确实没有数据点,所以密度估计在中间区域的概率极低,空白是正常现象。如果想让填充视觉上更连贯,可以尝试:
- 减少
bins数量,比如把bins=20改成bins=10,扩大等高线间隔,减少空白区域的占比; - 改用
geom="contour_filled"(ggplot2 3.3.0及以上版本支持),它的填充逻辑更适配多峰数据,能避免多边形拼接的缝隙:
ggplot(data=test_data,aes(x = X206.204 , y = X207.204))+ stat_density_2d(geom="contour_filled",n=800,bins=15, aes(fill = ..level..)) + geom_point(color="red")+ labs( x = expression({}^206*"Pb/"*{}^204*"Pb"), y = expression({}^207*"Pb/"*{}^204*"Pb") )+ theme_bw() + theme(panel.grid = element_blank(), axis.text.x = element_text(margin = margin(t = 5, unit = "pt")), axis.text=element_text(size=18), axis.title = element_text(size=22), legend.position="none")+ scale_fill_gradient(low = "cyan1",high = "cyan4")+ scale_x_continuous(breaks = seq(17, 19.6, by = 0.2), limits = c(17,19.6))+ scale_y_continuous(breaks = seq(15.4, 15.9, by = 0.1), limits = c(15.4, 15.9))
你也可以先跑下面的代码确认数据的真实分布,就能更直观理解中间空白的原因:
ggplot(test_data, aes(X206.204, X207.204)) + geom_point(color="red")
内容的提问来源于stack exchange,提问作者Gary Hsu
相关产品推荐
相关产品推荐

