为何在ggplot2的Aesthetic映射中指定fill会改变密度图的显示效果
问题原因
你遇到的两次geom_density输出不一致的核心原因是第二个图层的映射设置触发了自动分组计算:
- 第一个
geom_density没有额外的分组映射,是对全部395条成绩数据整体计算核密度,输出的是全量数据的密度曲线。 - 第二个
geom_density在aes()中传入了fill = q_aprox(0.025) < G3 & G3 < q_aprox(0.975),ggplot2会自动按照这个逻辑值将数据拆分为「符合区间条件」和「不符合区间条件」两个独立分组,分别对两组数据计算核密度,再按照你设置的position = 'stack'参数将两组密度堆叠展示,最终呈现的曲线自然和全量数据的密度曲线存在明显差异,也就是你观察到的左尾更宽、整体更尖锐的现象。
正确实现局部高亮的代码示例
如果想要保持密度曲线和全量计算结果一致,仅高亮95%置信区间的区域,可以参考以下两种写法:
写法1:用xlim限制高亮范围(简单直观)
grades <- student_data$G3 q_low <- qnorm(0.025, mean(grades), sd(grades)) q_high <- qnorm(0.975, mean(grades), sd(grades)) ggplot(student_data, aes(x = G3)) + # 绘制全量密度的基础样式 geom_density(color = 'steelblue', fill = 'lightgray', alpha = 0.3) + # 叠加95%区间内的高亮填充 geom_density(fill = 'steelblue', alpha = 0.5, xlim = c(q_low, q_high)) + theme_minimal()
写法2:用after_stat控制填充(精度更高)
ggplot(student_data, aes(x = G3)) + geom_density( aes(fill = after_stat(ifelse(x > q_low & x < q_high, "区间内", "区间外"))), color = 'steelblue', alpha = 0.3 ) + # 自定义填充色,不需要显示图例可以加guides(fill = "none") scale_fill_manual(values = c("区间内" = "steelblue", "区间外" = "lightgray")) + theme_minimal()
内容的提问来源于stack exchange,提问作者Ayhon Iron
相关产品推荐
相关产品推荐

