如何让R语言ggplot2分组柱状图中geom_jitter点显示在对应柱子内
问题修复方案
你遇到的散点错位问题由两个核心配置错误导致,对应修改方法如下:
错误原因
- 散点图层
geom_jitter使用了汇总后的均值数据集df.summary,而非包含所有原始观测值的原始数据集df,无法正确展示每个原始样本的散点 - 没有使用适配分组躲避场景的散点位置函数,散点没有和对应浓度的柱子进行对齐
修复后的完整代码
library(dplyr) library(ggplot2) library(plotly) library(ggpubr) df <- data.frame(Sample = c("0.5-1 DMSO (24) CD3-28","0.5-1 DMSO (24) CD3-28","0.5-1 DMSO (24)", "0.5-1 DMSO (24)","1-1 DMSO (24) CD3-28","1-1 DMSO (24) CD3-28", "1-1 DMSO CD3-28","1-1 DMSO","1-1 DMSO (24)","1-1 DMSO (24)","3-1 DMSO", "3-1 DMSO (24)","3-1 DMSO (24)","3-1 DMSO (24) BR","3-1 DMSO (24) BR CD3-28", "3-1 DMSO CD3-28","3-1 DMSO (24) CD3-28","3-1 DMSO (24) CD3-28", "0.5-1 0.1uM (24) CD3-28","0.5-1 0.1uM (24) CD3-28","0.5-1 0.1uM (24)", "0.5-1 0.1uM (24)","1-1 0.1uM (24) CD3-28","1-1 0.1uM (24) CD3-28","1-1 0.1uM CD3-28", "1-1 0.1uM","1-1 0.1uM (24)","1-1 0.1uM (24)","3-1 0.1uM","3-1 0.1uM (24)", "3-1 0.1uM (24)","3-1 0.1uM (24) BR","3-1 0.1uM (24) BR CD3-28","3-1 0.1uM CD3-28", "3-1 0.1uM (24) CD3-28","3-1 0.1uM (24) CD3-28","0.5-1 1uM (24) CD3-28", "0.5-1 1uM (24) CD3-28","0.5-1 1uM (24)","0.5-1 1uM (24)","1-1 1uM (24) CD3-28", "1-1 1uM (24) CD3-28","1-1 1uM CD3-28","1-1 1uM (24)","1-1 1uM (24)","1-1 1uM", "3-1 1uM","3-1 1uM (24)","3-1 1uM (24)","3-1 1uM (24) BR","3-1 1uM (24) BR CD3-28", "3-1 1uM CD3-28","3-1 1uM (24) CD3-28","3-1 1uM (24) CD3-28"), Group = c("0.5_1 + Stim","0.5_1 + Stim","0.5_1","0.5_1","1_1 + Stim","1_1 + Stim","1_1 + Stim","1_1","1_1","1_1", "3_1","3_1","3_1","3_1 + BR","3_1 + BR","3_1 + Stim","3_1 + Stim","3_1 + Stim","0.5_1 + Stim","0.5_1 + Stim", "0.5_1","0.5_1","1_1 + Stim","1_1 + Stim","1_1 + Stim","1_1","1_1","1_1","3_1","3_1","3_1","3_1 + BR", "3_1 + BR","3_1 + Stim","3_1 + Stim","3_1 + Stim","0.5_1 + Stim","0.5_1 + Stim","0.5_1","0.5_1","1_1 + Stim", "1_1 + Stim","1_1 + Stim","1_1","1_1","1_1","3_1","3_1","3_1","3_1 + BR","3_1 + BR","3_1 + Stim","3_1 + Stim","3_1 + Stim"), Concentration = c("DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO","DMSO", "DMSO","DMSO","DMSO","DMSO","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM", "0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","0.1uM","1uM","1uM","1uM","1uM", "1uM","1uM","1uM","1uM","1uM","1uM","1uM","1uM","1uM","1uM","1uM","1uM","1uM","1uM"), Marker = c(29.1,35.5,20,11.8,48.9,41.2,19.4,2.49,21.6,17.7,5.52,51.5,42.5,8.5,45.2,17.1, 67,58.5,42.7,36.4,16,22.4,42.2,50.3,33.4,5.88,27.9,21.5,22.9,62.5,35.3,17,50.4, 49,65.2,65.3,52.9,37.3,19.1,16.1,52.7,46.5,45.1,30.9,28.9,6.62,13.1,87.4,52.1,19.8,63.7,55.3,88.4,66.4)) # 先将原始数据的浓度列转为因子,保证分组顺序正确 df$Concentration <- factor(df$Concentration, levels=c("DMSO","0.1uM","1uM")) df.summary <- df %>% dplyr::group_by(Sample, Group, Concentration) %>% dplyr::summarize(sd = sd(Marker, na.rm = TRUE), Marker = mean(Marker), .groups = "drop") p <- ggplot(data = df.summary, aes(x = Group, y = Marker, fill = Concentration)) + geom_bar(stat="identity", position=position_dodge(.9)) + # 散点使用原始数据,位置用jitterdodge对齐分组柱子 geom_jitter(data = df, aes(x = Group, y = Marker), position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.9), color = "black") + geom_errorbar(aes(ymin = Marker - sd, ymax = Marker + sd), width = 0.2, position=position_dodge(0.9)) + scale_fill_manual(values = c("DMSO" = '#619CFF',"0.1uM" = '#F8766D',"1uM" = '#00BA38')) + theme_bw() p <- ggpar(p, x.text.angle = 45) ggplotly(p)
关键修改说明
- 给原始数据集的
Concentration列设置因子顺序,保证分组、填充色和柱子顺序匹配 - 散点图层切换为使用原始数据集
df,位置函数替换为position_jitterdodge,设置dodge.width=0.9和柱子的躲避宽度一致实现跨分组对齐,jitter.width=0.2控制同一柱子内散点的抖动幅度,避免超出柱子范围 - 移除误差棒映射中冗余的
df.summary$前缀,避免环境变量引用错误
内容的提问来源于stack exchange,提问作者RanonKahn
相关产品推荐
相关产品推荐

