如何用ggplot绘制年度实例计数柱状图+年度伤亡总和折线图?
解决ggplot中年度实例数柱状图+伤亡总和折线图的匹配问题
问题根源
你遇到的问题核心原因有三个:
- x轴类型不匹配:主图层的x是
factor(year)(离散型),但折线图用的casualties_by_year里的year是数值型,两者刻度无法对齐,导致折线错位。 - 折线分组缺失:离散x轴下,ggplot默认每个x值为单独分组,不指定
group=1的话无法将多个点连接成折线。 - y轴数值范围差异大:实例数(最大值4)和伤亡总和(最大值41)差距悬殊,单y轴会让折线被压缩到几乎不可见。
修正后的完整代码
我们可以先统一聚合年度统计数据(逻辑更清晰):
# 加载包 library(ggplot2) # 聚合年度实例数和伤亡总和 instances_by_year <- aggregate(uid ~ year, data = data, FUN = length) colnames(instances_by_year)[2] <- "instances" casualties_by_year <- aggregate(casualties ~ year, data = data, FUN = sum) yearly_data <- merge(instances_by_year, casualties_by_year, by = "year") # 绘制图表 ggplot(yearly_data, aes(x = factor(year))) + # 柱状图:年度实例数 geom_bar(aes(y = instances), width = 0.4, fill = 'darkorange', stat = "identity") + # 折线图:年度伤亡总和,指定group=1确保连线 geom_line(aes(y = casualties, group = 1), color = "darkblue", size = 1) + # 设置双y轴适配数值范围 scale_y_continuous( name = "年度实例数", sec.axis = sec_axis(trans = ~ ., name = "年度伤亡总和") ) + scale_x_discrete(name = "年份") + theme_minimal()
如果不想提前聚合实例数,直接用原数据画柱状图的写法:
ggplot() + # 原数据直接统计年度实例数 geom_bar(data = data, aes(x = factor(year)), width = 0.4, fill = 'darkorange') + # 折线图用聚合后的伤亡数据,统一x轴类型+指定group=1 geom_line(data = casualties_by_year, aes(x = factor(year), y = casualties, group = 1), color = "darkblue", size = 1) + scale_y_continuous( name = "年度实例数", sec.axis = sec_axis(~ ., name = "年度伤亡总和") ) + theme_minimal()
关键修正点解析
- 统一x轴类型:将折线图的x也设置为
factor(year),和柱状图的x轴刻度完全对齐,避免错位。 - 添加
group=1:在geom_line的aes中指定group=1,强制ggplot将所有年份归为同一组,这样才能把离散的点连接成折线。 - 双y轴适配:通过
sec_axis添加第二个y轴,解决两类数据数值范围差距大导致的可视化问题,让折线和柱状图都能清晰展示。 stat="identity":当使用提前聚合的实例数数据时,需要指定这个参数,告诉ggplot直接使用我们提供的y值,而不是默认的计数统计。
内容的提问来源于stack exchange,提问作者muds
相关产品推荐
相关产品推荐

