如何用ggplot绘制按Race/Sex/Language分组的柱状图并添加显著性标记?
问题:ggplot实现分组聚合的x轴布局并添加显著性标记
我有如下结构的DataFrame:
# dput输出 structure(list(Group = structure(c(1L, 5L, 2L, 3L, 4L, 6L, 7L, 8L, 9L), levels = c("White", "NA", "Other Race", "Two Races", "Asian", "Female", "Male", "Mandarin", "Spanish"), class = "factor"), emmean = c(1.8, 2.1, 1.5, 1.9, 1.6, 1.7, 2, 1.4, 1.9), SE = c(0.4, 0.5, 0.3, 0.5, 0.4, 0.4, 0.5, 0.4, 0.5), df = c(22483, 22483, 22483, 22483, 22483, 22483, 22483, 22483, 22483), lower.CL = c(1.3, 1.2, 1, 1.5, 1.2, 1.3, 1.6, 1.1, 1.5), upper.CL = c(2.3, 2.4, 1.8, 2.3, 1.9, 2, 2.5, 1.8, 2.3), Measure = c("Measure", "Measure", "Measure", "Measure", "Measure", "Measure", "Measure", "Measure", "Measure"), fill = c("Race", "Race", "Race", "Race", "Race", "Sex", "Sex", "Language", "Language")), row.names = c(6L, 7L, 8L, 9L, 10L, 13L, 14L, 17L, 18L), class = "data.frame")
尝试用以下ggplot代码绘制按Race、Sex、Language分组的柱状图,但生成的图表未实现分类组聚合的x轴布局,希望得到分组样式,同时在Asian与参考组White之间添加显著性标记(如星号):
ggplot(plot_data_custom, aes(x = Group, y = emmean, fill = fill)) + geom_bar(stat = "identity", position = position_dodge(width = 0.7), width = 0.7, color = "black") + geom_errorbar(aes(ymin = lower.CL, ymax = upper.CL), position = position_dodge(width = 0.7), width = 0.2, color = "black") + labs(title = "Measure", y = "Adjusted Value", x = NULL) + scale_fill_manual(values = professional_palette, limits = legend_order) + scale_y_continuous(limits = c(0, 3.5), breaks = seq(0, 3.5, by = 0.5)) + theme_bw() + theme(legend.position = "bottom", axis.text.x = element_text(angle = 45, hjust = 1), panel.grid.major = element_line(color = "lightgray", size = 0.2), panel.grid.minor = element_blank(), axis.line = element_line(color = "black"), plot.title = element_text(face = "bold", size = 14), legend.text = element_text(size = 10), legend.key.size = unit(1.5, "lines"), plot.margin = unit(c(1, 1, 1, 1), "cm")) + guides(fill = guide_legend(title = NULL))
解决方案
1. 实现x轴分组聚合布局
要将Race、Sex、Language三类分组展示,推荐使用facet_wrap按fill字段分栏,同时调整Group的因子顺序,确保同类别的分组排列合理:
# 重新指定Group的因子顺序,按类别聚合排列 plot_data_custom$Group <- factor(plot_data_custom$Group, levels = c("White", "Asian", "NA", "Other Race", "Two Races", "Female", "Male", "Mandarin", "Spanish"))
分面后每个类别会作为独立栏位,x轴仅显示对应类别下的分组,无需再用position_dodge。
2. 添加显著性标记
通过geom_segment和geom_text手动添加White与Asian之间的显著性星号,也可以使用ggsignif包简化操作,这里给出基础ggplot实现方式:
# 定义显著性标记的位置数据 signif_data <- data.frame( x = 1, xend = 2, # White和Asian在Race分栏中的x轴位置 y = 2.5, yend = 2.5, # 标记线的y轴高度 fill = "Race", label = "*" # 显著性标记 )
完整可运行代码
library(ggplot2) # 调整Group因子顺序 plot_data_custom$Group <- factor(plot_data_custom$Group, levels = c("White", "Asian", "NA", "Other Race", "Two Races", "Female", "Male", "Mandarin", "Spanish")) # 定义显著性标记数据 signif_data <- data.frame( x = 1, xend = 2, y = 2.5, yend = 2.5, fill = "Race", label = "*" ) # 绘制图表 ggplot(plot_data_custom, aes(x = Group, y = emmean, fill = fill)) + geom_bar(stat = "identity", width = 0.7, color = "black") + geom_errorbar(aes(ymin = lower.CL, ymax = upper.CL), width = 0.2, color = "black") + # 添加显著性标记的横线和星号 geom_segment(data = signif_data, aes(x = x, xend = xend, y = y, yend = yend), color = "black") + geom_text(data = signif_data, aes(x = (x+xend)/2, y = y + 0.1, label = label), size = 6) + labs(title = "Measure", y = "Adjusted Value", x = NULL) + # 自定义填充色,可替换为你需要的professional_palette scale_fill_manual(values = c("Race" = "#1f77b4", "Sex" = "#ff7f0e", "Language" = "#2ca02c"), limits = c("Race", "Sex", "Language")) + scale_y_continuous(limits = c(0, 3), breaks = seq(0, 3, by = 0.5)) + # 分面实现分组布局,free_x让每个分栏的x轴独立 facet_wrap(~fill, scales = "free_x", nrow = 1) + theme_bw() + theme(legend.position = "bottom", axis.text.x = element_text(angle = 45, hjust = 1), panel.grid.major = element_line(color = "lightgray", size = 0.2), panel.grid.minor = element_blank(), axis.line = element_line(color = "black"), plot.title = element_text(face = "bold", size = 14), legend.text = element_text(size = 10), legend.key.size = unit(1.5, "lines"), plot.margin = unit(c(1, 1, 1, 1), "cm"), # 去掉分面标题,图例已展示类别信息 strip.text = element_blank()) + guides(fill = guide_legend(title = NULL))
内容的提问来源于stack exchange,提问作者Jamie
相关产品推荐
相关产品推荐

