叠加geom_bar图表问题:X轴显示不全、填充色及颜色混淆
解决ggplot2叠加柱状图的三个问题
核心前提:整理为整洁数据(Tidy Data)
ggplot2的设计逻辑更适配单数据框+分类列的整洁格式,先把三个年度的数据合并并添加Year标记列,这是解决所有问题的基础:
# 合并三个年度数据,新增Year列标记年份 PerfDistCombined <- rbind( cbind(PerfDist2019, Year = "2019"), cbind(PerfDist2020, Year = "2020"), cbind(PerfDist2021, Year = "2021") ) # 强制指定Districts的因子水平,包含所有需要显示的区域(1-25、31) PerfDistCombined$Districts <- factor(PerfDistCombined$Districts, levels = c(1:25, 31))
问题1:X轴无法显示全部区域
原因:部分区域可能在单个年度数据中缺失,ggplot默认只会显示有数据的因子水平。
解决方法:
- 上述代码已通过
factor(..., levels = c(1:25, 31))强制定义所有需要的区域为因子水平; - 绘图时添加
scale_x_discrete(drop = FALSE),强制显示所有因子水平(即使某年份该区域无数据,会显示高度为0的柱子)。
问题2:无法设置填充色fill
原因:原代码中fill = "2019"写在aes()内部,ggplot会将其当作映射变量而非直接的颜色值,导致自定义填充色不生效。
解决方法:
合并数据后,将Year作为fill的映射变量,配合scale_fill_manual()手动指定各年份的填充色,既能生效又能生成正确的图例:
scale_fill_manual(values = c("2019" = "red", "2020" = "green", "2021" = "blue"))
问题3:叠加颜色混淆难以区分
原因:默认的叠加(position = "identity")会让柱子重叠,透明度调整后仍易混淆。推荐改用并列柱状图,更直观展示年度差异:
在geom_bar()中设置position = position_dodge(width = 0.8),让同区域的三年柱子并排显示。
完整代码示例(推荐并列柱状图版本)
library(ggplot2) library(scales) # 用于百分比格式 # 合并并整理数据 PerfDistCombined <- rbind( cbind(PerfDist2019, Year = "2019"), cbind(PerfDist2020, Year = "2020"), cbind(PerfDist2021, Year = "2021") ) PerfDistCombined$Districts <- factor(PerfDistCombined$Districts, levels = c(1:25, 31)) # 绘图 ggplot(PerfDistCombined, aes(x = Districts, y = Perf, fill = Year)) + geom_bar(stat = "identity", position = position_dodge(width = 0.8), alpha = 0.8, color = "black") + scale_fill_manual(values = c("2019" = "red", "2020" = "green", "2021" = "blue")) + scale_x_discrete(drop = FALSE) + scale_y_continuous(labels = percent_format()) + # Y轴设为百分比 labs(x = "区域", y = "性能百分比", fill = "年份") + theme(axis.text.x = element_text(angle = 45, hjust = 1)) # 旋转X轴标签避免重叠
可选:叠加柱状图优化版本
如果坚持用叠加方式,调整颜色对比度和透明度,减少混淆:
ggplot(PerfDistCombined, aes(x = Districts, y = Perf, fill = Year)) + geom_bar(stat = "identity", position = "identity", alpha = 0.6, color = "black") + scale_fill_manual(values = c("2019" = "#e74c3c", "2020" = "#2ecc71", "2021" = "#3498db")) + scale_x_discrete(drop = FALSE) + scale_y_continuous(labels = percent_format()) + labs(x = "区域", y = "性能百分比", fill = "年份") + theme(axis.text.x = element_text(angle = 45, hjust = 1))
内容的提问来源于stack exchange,提问作者Léo
相关产品推荐
相关产品推荐

