ggplot2如何在二维散点图中绘制单维度连续密度背景
ggplot2 一维X轴密度背景实现方案
原手动拼接矩形的实现效果如下,存在明显条带、边距覆盖不全、填充映射冲突问题:
核心用内置stat_density统计变换搭配geom_raster实现,不需要手动预计算密度值、拼接矩形,可直接解决提到的三个问题:
- 条带效应问题:
geom_raster为连续栅格渲染,搭配stat_density输出的高密度核密度估计网格,不会出现矩形拼接的边界重叠、透明度条带,默认512网格已经足够平滑,可调高n参数获得更细腻的效果。 - 边距覆盖问题:给栅格设置
height = Inf参数,可自动沿Y轴撑满整个绘图区,包括ggplot默认生成的扩展边距,无需手动计算Y轴范围、关闭坐标扩展。 - 填充映射冲突问题:可通过两种方式解决:一是散点使用
color美学映射,完全不占用fill通道;二是使用ggnewscale包的new_scale_fill()函数,为不同图层设置完全独立的填充标度,不存在底层机制限制。
无额外依赖最简实现
散点用颜色映射区分分组,不需要安装其他包,代码比原方案简洁70%:
library(ggplot2) data(iris) ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + # 一维密度背景层 stat_density( aes(x = Sepal.Length, y = mean(range(Sepal.Width)), fill = after_stat(density), height = Inf), geom = "raster", alpha = 0.5, n = 1024, inherit.aes = FALSE ) + scale_fill_viridis_c(option = "A", guide = "none") + geom_point(aes(color = Species), size = 2, alpha = 0.8) + scale_color_brewer(palette = "Set1", name = "鸢尾花种类") + geom_rug(sides = "b")
支持散点独立填充映射的版本
如果需要散点也使用fill映射(比如用带填充的实心点形状),搭配ggnewscale即可实现双独立填充色板:
library(ggplot2) library(ggnewscale) data(iris) ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + # 密度背景层 stat_density( aes(x = Sepal.Length, y = mean(range(Sepal.Width)), fill = after_stat(density), height = Inf), geom = "raster", alpha = 0.5, n = 1024, inherit.aes = FALSE ) + scale_fill_viridis_c(option = "A", name = "X轴分布密度") + # 重置填充标度,后续图层独立使用fill映射 new_scale_fill() + # 散点层,独立填充 geom_point(aes(fill = Species), shape = 21, size = 2, alpha = 0.8) + scale_fill_brewer(palette = "Set1", name = "鸢尾花种类") + geom_rug(sides = "b")
实现效果和示例需求完全一致,密度条带平滑无锯齿,自动覆盖全绘图区,散点映射不受密度层干扰。
内容的提问来源于stack exchange,提问作者shians
相关产品推荐
相关产品推荐

