基于ggplot2的带个体与整体均值的箱线图绘制及排序问题
箱线图排序异常与自定义颜色失效问题修复
我需要绘制一幅箱线图,要求:
- 每个行为类别对应一个箱线,隐藏箱线的异常值
- 用红色大点显示该行为类别的整体均值
- 抖动显示数据集中9个个体在该行为下的均值(替换原来的原始数据抖动,避免图表混乱)
但修改代码后,出现两个问题:
- 行为类别无法按指定顺序排列
- 自定义填充颜色失效
初始代码
library(ggplot2) ggplot(Seen2, aes(x=Behaviour, y=Roll_Avg, fill=Behaviour)) + geom_boxplot(outlier.shape= NA) + geom_point(aes(fill=Behaviour), size=2, position=position_jitter(width=0.2, height=0.1)) + stat_summary(fun=mean, geom="point", shape=20, size=5, color="red", fill="red") + theme_classic() + my_scale + theme(axis.text.y=element_text(size=16, angle=0))+ ylim(-30, 30)
更新后(排序失效)的代码
my_colors <- c("#CCFFFF", "#000000", "#7F7F7F", "#336699", "#008080", "#00CCFF", "#264AE2") names(my_colors) <- levels(factor(c((Seen2$Behaviour), levels(Seen2$Behaviour)))) my_scale <- scale_fill_manual(name="Behaviour", values=my_colors,) behavssec$Behaviour <- factor(Seen2$Behaviour, levels=c("Burst", "High energy swimming", "Medium energy swimming", "Low energy swimming", "Travel", "Ascending", "Descending")) ggplot(Seen2, aes(x=Behaviour, y=Roll_Avg, fill=Behaviour)) + geom_boxplot(outlier.shape= NA) + geom_point(data=means, size=2, position=position_jitter(width=0.2, height=0.1)) + stat_summary(fun=mean, geom="point", shape=20, size=5, color="red", fill="red") + theme_classic() + my_scale + theme( axis.text.y= element_text( size=16, angle =0)) + ylim(-30, 30)
数据集
Seen2 <- structure(list(SharkID = c(9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L), Behaviour = c("Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "Travel", "Travel", "Travel", "Travel", "Travel", "Burst", "Burst", "Burst", "Burst", "Burst", "Ascending", "Ascending", "Ascending", "Ascending", "Ascending", "Ascending", "Ascending", "Descending", "Descending", "Descending", "Descending", "Descending", "Descending", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "Burst", "Burst", "Burst", "Burst", "Burst", "Burst", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "Low.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "High.energy.swimming", "Burst", "Burst", "Burst", "Burst", "Burst", "Burst", "Burst", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming", "Medium.energy.swimming"), Roll_Avg = c(3.97084, 3.90604, 3.90738, 3.80425, 3.4154, -0.993225, -0.940408, -0.55992, -0.791121, -1.83573, -3.41667, -14.0837, -14.9381, -16.4732, -16.6994, -15.5318, -18.2402, -19.4427, -22.8129, -27.009, -27.3907, 17.3778, 13.4861, 7.82564, 4.63057, 6.94956, 14.3372, 22.0873, -11.5397, -11.7741, -11.4795, -10.7844, -10.5135, -11.0162, -90, -90, 11.0157, 6.13595, 2.2689, -0.710414, -5.56132, -12.0987, -9.70231, -7.13388, -5.41693, -4.23157, 2.11092, 2.19057, 1.5597, 0.637742, 1.17135, 3.41601, 4.71664, 4.61525, -0.813111, -4.45238, -7.43746, -9.11626, -9.94338, -11.0361, -11.8852, -10.472, -5.12697, 2.61247, 9.80993, 17.307, 10.5466, -4.01104, -7.40708, -2.72602, -5.43834, -5.22419, -4.8472, -4.43957, -1.67914, 2.39693, 7.84736, -9.7158, -8.70349, -8.22463, -8.22878, -9.43265, -0.527293, -0.283262, -0.614311, -0.380123, -0.344986, 7.73204, 7.47037, 7.00224, 7.01661, 7.38737, 7.83069, -1.83138, -1.7847, -1.68084, -1.61196, -1.49905, -1.61391, -1.46356, -0.986477, -0.806394, -0.883015, -0.840026, -0.727501, -1.15641, -1.28692, -1.38961, -1.43838, -1.42089, -1.27225)), class = "data.frame", row.names = c(NA, -111L))
问题根源
- 排序失效:
- 错误修改了
behavssec$Behaviour而非目标数据集Seen2$Behaviour的因子水平 - 指定的排序名称是空格分隔(如
"Low energy swimming"),但数据中实际行为名称是点分隔(如"Low.energy.swimming"),两者不匹配导致排序规则失效
- 错误修改了
- 颜色失效:
- 自定义颜色的命名基于原始行为因子水平,未与修改后的排序levels对应
- 缺失个体均值数据集:代码中使用了
means但未提前计算,无法显示个体均值
修正后的完整代码
library(ggplot2) library(dplyr) # 1. 计算每个个体在各行为下的均值 means <- Seen2 %>% group_by(SharkID, Behaviour) %>% summarise(Roll_Avg = mean(Roll_Avg, na.rm = TRUE), .groups = "drop") # 2. 定义行为排序顺序(与数据中的点分隔名称一致) behav_order <- c("Burst", "High.energy.swimming", "Medium.energy.swimming", "Low.energy.swimming", "Travel", "Ascending", "Descending") # 3. 统一主数据集和均值数据集的因子水平,确保排序生效 Seen2$Behaviour <- factor(Seen2$Behaviour, levels = behav_order) means$Behaviour <- factor(means$Behaviour, levels = behav_order) # 4. 定义与排序匹配的自定义颜色 my_colors <- c("#CCFFFF", "#000000", "#7F7F7F", "#336699", "#008080", "#00CCFF", "#264AE2") names(my_colors) <- behav_order my_scale <- scale_fill_manual(name = "Behaviour", values = my_colors) # 5. 绘制箱线图 ggplot(Seen2, aes(x = Behaviour, y = Roll_Avg, fill = Behaviour)) + geom_boxplot(outlier.shape = NA) + # 绘制个体均值抖动点,明确映射关系 geom_point(data = means, aes(x = Behaviour, y = Roll_Avg), size = 2, position = position_jitter(width = 0.2, height = 0.1)) + # 绘制整体均值红点 stat_summary(fun = mean, geom = "point", shape = 20, size = 5, color = "red", fill = "red") + theme_classic() + my_scale + theme(axis.text.y = element_text(size = 16, angle = 0)) + ylim(-30, 30)
关键修改说明
- 用
dplyr计算个体均值数据集means,确保每个个体-行为组合的均值正确 - 统一行为名称格式,同步修改主数据集和均值数据集的因子水平,保证排序规则生效
- 自定义颜色的命名直接使用排序后的行为列表,与因子levels完全匹配,解决颜色失效问题
- 明确指定抖动点的映射关系,避免数据集切换导致的映射错误
内容的提问来源于stack exchange,提问作者Sharklady
相关产品推荐
相关产品推荐

