如何在ggplot的facet_wrap中添加年份×处理多分组的均值?
问题描述
使用ggplot2的facet_wrap按品种分面绘制图表时,希望为每个分面内的2个年份×2种处理共4个交叉分组添加均值文本或竖线。此前尝试group_by仅能实现单分组(年份或处理)的均值计算,询问是否可以实现年份与处理双分组的均值添加。
原始数据
structure(list(Year = c(2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017), Pos_heliaphen = c("W13", "W44", "X23", "Y42", "Z07", "Z36", "W45", "X22", "X30", "Y43", "Z06", "Z37", "Y36", "Z06", "Z18", "Z24", "Z40", "Z43", "Y35", "Z05", "Z17", "Z23", "Z39", "Z44"), Treatment = c("Non-irrigated", "Non-irrigated", "Non-irrigated", "Non-irrigated", "Non-irrigated", "Non-irrigated", "Irrigated", "Irrigated", "Irrigated", "Irrigated", "Irrigated", "Irrigated", "Non-irrigated", "Non-irrigated", "Non-irrigated", "Non-irrigated", "Non-irrigated", "Non-irrigated", "Irrigated", "Irrigated", "Irrigated", "Irrigated", "Irrigated", "Irrigated" ), Variety = c("ES Pallador - MG I", "ES Pallador - MG I", "ES Pallador - MG I", "Sultana - MG 000", "Sultana - MG 000", "Sultana - MG 000", "ES Pallador - MG I", "ES Pallador - MG I", "ES Pallador - MG I", "Sultana - MG 000", "Sultana - MG 000", "Sultana - MG 000", "ES Pallador - MG I", "ES Pallador - MG I", "ES Pallador - MG I", "Sultana - MG 000", "Sultana - MG 000", "Sultana - MG 000", "ES Pallador - MG I", "ES Pallador - MG I", "ES Pallador - MG I", "Sultana - MG 000", "Sultana - MG 000", "Sultana - MG 000"), SLA = c(127.105797101449, 135.263238679969, 135.57233201581, 120.477777777778, 149.139664804469, 139.5776, 142.927987742594, 139.450256889304, 152.589150943396, 102.962703962704, 114.160714285714, 106.182042833608, 29.168895183201, 61.5906086966241, 14.65223598377, 73.8218290951699, 29.0006487652397, 37.6144729444593, 103.550713082565, 118.558911914481, 116.11947891962, 91.7471974108231, 78.2428634817335, 91.5116772823779)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -24L))
现有绘图代码
library(ggplot2) library(dplyr) df %>% mutate(across(Variety, factor, levels=c("Sultana - MG 000","ES Pallador - MG I","Isidor - MG I", "Santana - MG I/II","Blancas - MG II","Ecudor - MG II")))%>% ggplot(aes(y=Treatment,x=SLA,group=Year))+ geom_point(aes(color = as.factor(Year),shape=Treatment),size=3,alpha = 0.7)+ labs(x = expression(paste('SLA (cm'^2,'·','g'^-1,')')), y = "Treatment")+ scale_color_manual(values = c("#FF6600","#336699"))+ scale_shape_manual(values = c(16,1))+ theme_bw() + theme(axis.text.x = element_text(size=13,vjust=0.5), axis.text.y = element_text(size=13), axis.title.x = element_text(size = 14), axis.title.y = element_text(size = 14), legend.title=element_text(size=14), legend.text=element_text(size=12), legend.position = "bottom" )+ guides(color = guide_legend(title = "Year"),shape = guide_legend(title = "Treatment"))+ facet_wrap(~Variety)
解决方案
完全可以实现双分组的均值添加,核心是先通过group_by同时按**品种(Variety)、年份(Year)、处理(Treatment)**三个维度分组计算均值,再将计算结果传入ggplot中添加对应的图层。
步骤1:预处理计算交叉分组均值
# 计算每个品种-年份-处理组合的SLA均值 mean_df <- df %>% group_by(Variety, Year, Treatment) %>% summarise(mean_SLA = mean(SLA, na.rm = TRUE), .groups = "drop")
步骤2:更新绘图代码,添加均值竖线与文本
df %>% mutate(across(Variety, factor, levels=c("Sultana - MG 000","ES Pallador - MG I","Isidor - MG I", "Santana - MG I/II","Blancas - MG II","Ecudor - MG II"))) %>% ggplot(aes(y=Treatment,x=SLA,group=Year))+ # 原始散点图层 geom_point(aes(color = as.factor(Year),shape=Treatment),size=3,alpha = 0.7)+ # 添加均值竖线:对应每个交叉分组的均值位置,颜色匹配年份 geom_vline(data = mean_df, aes(xintercept = mean_SLA, color = as.factor(Year)), linetype = "dashed", linewidth = 1)+ # 添加均值文本:标注在竖线右侧,保留1位小数 geom_text(data = mean_df, aes(x = mean_SLA, y = Treatment, label = round(mean_SLA, 1), color = as.factor(Year)), hjust = -0.2, size = 4)+ labs(x = expression(paste('SLA (cm'^2,'·','g'^-1,')')), y = "处理方式")+ scale_color_manual(values = c("#FF6600","#336699"))+ scale_shape_manual(values = c(16,1))+ theme_bw() + theme(axis.text.x = element_text(size=13,vjust=0.5), axis.text.y = element_text(size=13), axis.title.x = element_text(size = 14), axis.title.y = element_text(size = 14), legend.title=element_text(size=14), legend.text=element_text(size=12), legend.position = "bottom" )+ guides(color = guide_legend(title = "年份"),shape = guide_legend(title = "处理方式"))+ facet_wrap(~Variety)
代码说明
group_by(Variety, Year, Treatment):同时按三个维度分组,确保每个分面(品种)内的每个年份-处理交叉组都能计算出独立的均值geom_vline:利用预处理的均值数据绘制垂直参考线,线型设为虚线便于区分原始数据点geom_text:将均值数值标注在竖线右侧,hjust=-0.2避免文本与竖线重叠,round()简化数值显示
内容的提问来源于stack exchange,提问作者Chouette
相关产品推荐
相关产品推荐

