R语言ggplot如何绘制组内百分比分组条形图
问题根源
原有代码输出不符合预期,核心原因有两点:
- 错误将连续型变量
Lanes.Cleared.Duration映射到y轴,搭配stat="identity"时会直接使用该字段的原始值作为条形高度,不会自动统计占比 - 未提前按
Durations(时长区间)分组,统计每个分组内不同Blocked.Lanes(封锁车道数)的发生频次,也未做组内占比换算
正确实现代码
先完成数据汇总计算组内占比,再调用ggplot绘图即可:
library(tidyverse) # 汇总计算每个时长组内不同封锁车道数的发生占比 plot_df <- data %>% mutate(Blocked.Lanes = factor(Blocked.Lanes)) %>% # 封锁车道数转为分类变量 group_by(Durations, Blocked.Lanes) %>% summarise(case_num = n(), .groups = "drop_last") %>% # 统计各组合的发生次数 mutate(occur_ratio = case_num / sum(case_num)) %>% # 计算组内占比 ungroup() # 绘制分组条形图 ggplot(plot_df, aes(x = Durations, y = occur_ratio, fill = Blocked.Lanes)) + geom_col(position = position_dodge(width = 0.8), width = 0.7) + scale_y_continuous(labels = scales::percent_format()) + # y轴显示为百分比格式 # 可选:添加条形数值标签 geom_text(aes(label = scales::percent(occur_ratio, accuracy = 0.1)), position = position_dodge(width = 0.8), vjust = -0.3, size = 3.2) + labs( x = "车道清场时长区间", y = "组内发生占比", fill = "封锁车道数" ) + theme_minimal()
代码说明
- 分组统计逻辑:先按时长区间、封锁车道数两个维度交叉计数,再保留时长区间的分组状态计算占比,保证每个时长区间内所有封锁车道数的占比之和为100%
geom_col()是ggplot2中专门用于预汇总数据的条形图函数,等价于geom_bar(stat = "identity"),写法更简洁- 调整
position_dodge()的宽度参数可以控制同组内条形的间距,避免条形重叠或分散 - 借助
scales::percent_format()可以直接将0-1区间的小数值自动转换为百分比显示,无需手动做数值换算
内容的提问来源于stack exchange,提问作者Mustafa Kamal
相关产品推荐
相关产品推荐

