如何使用stat_summary在ggplot2多面板密度图中添加均值竖线
解决ggplot多面板密度图添加分组均值竖线的问题
正确实现代码(stat_summary方式)
使用stat_summary时,需要通过after_stat(x)获取计算后的均值,并为geom_vline指定y方向范围,确保竖线覆盖密度图的高度:
set.seed(42) library(tidyverse) data_frame(site = rep(LETTERS[1:4], each = 25), sex = rep(c("f", "m"), 50), mass = rnorm(100, 50, 5)) %>% ggplot(aes(x = mass, col = sex)) + geom_density() + stat_summary( fun = mean, geom = "vline", aes(xintercept = after_stat(x)), # 提取stat_summary计算出的均值 yintercept = 0, yend = Inf, # 竖线从底部延伸到顶部 linetype = "dashed" # 可选:用虚线区分均值线和密度曲线 ) + facet_wrap(~site)
另一种直观方法(提前计算均值)
先按site和sex分组计算均值,再用geom_vline直接添加,逻辑更清晰:
set.seed(42) library(tidyverse) # 预处理:计算每个分组的均值 mean_df <- data_frame(site = rep(LETTERS[1:4], each = 25), sex = rep(c("f", "m"), 50), mass = rnorm(100, 50, 5)) %>% group_by(site, sex) %>% summarise(mean_mass = mean(mass), .groups = "drop") # 绘图 data_frame(site = rep(LETTERS[1:4], each = 25), sex = rep(c("f", "m"), 50), mass = rnorm(100, 50, 5)) %>% ggplot(aes(x = mass, col = sex)) + geom_density() + geom_vline(data = mean_df, aes(xintercept = mean_mass, col = sex), linetype = "dashed") + facet_wrap(~site)
之前错误的原因解析
- 第一次尝试:
stat_summary搭配geom_vline时,既没指定xintercept的来源(需要映射计算后的均值),也没给geom_vline设置y方向范围,导致报错缺少y美学。 - 第二次尝试:添加
y=0但未正确映射xintercept,geom_vline必须明确xintercept参数,而这里需要用stat_summary生成的统计值,不是原始数据。 - 第三次尝试:直接将
xintercept映射到原始数据的mass字段,导致每个数据点都生成一条竖线,而非分组计算后的均值。
内容的提问来源于stack exchange,提问作者tnt
相关产品推荐
相关产品推荐

