R语言ggplot2绘图实现X轴按人名分组的解决方法
核心问题说明
直接将X轴全局映射为City字段时,ggplot会自动聚合同一城市下的所有观测值,仅添加group=Name参数只能调整统计计算的分组逻辑,无法在离散X轴上自动拆分出人名维度的独立分组位置,因此无法实现预期效果。另外原代码存在两个影响结果的小问题:
- 提前将
city/Transport/time提取为全局独立向量,导致ggplot映射时无法关联到同一行的Name维度信息,分组逻辑容易失效 - 原始数据中
Bus值末尾带有多余空格,会被识别为独立的交通方式类别,导致填充色映射错误
实现方案
以下提供两种可直接运行的实现方案,均满足X轴映射City、Y轴映射Time、填充色区分Transport、按Name分组的要求。
方案1:分面分组(优先推荐,可读性最高)
将人名作为独立分面放在X轴下方,每个分面内展示对应城市不同交通方式的耗时,逻辑清晰,不会出现X轴标签拥挤、柱子重叠的问题,代码可维护性更强。
library(ggplot2) library(viridis) # 数据清洗:去除Transport字段首尾多余空格 myData$Transport <- trimws(myData$Transport) p <- ggplot(myData, aes(x = City, y = Time, fill = Transport)) + # 用geom_col替代geom_bar(stat="identity"),代码更简洁 geom_col(position = position_dodge(width = 0.8), width = 0.7) + scale_fill_viridis(discrete = TRUE, option = "D") + # 按Name维度分面,实现分组效果,分面放在X轴底部 facet_wrap(~Name, nrow = 1, strip.position = "bottom") + scale_y_continuous(limits = c(0, 10), breaks = seq(0, 10, by = 1)) + labs(x = "City / Name", y = "Time", title = "People", fill = "Transport") + # 自定义主题,保留原代码的样式设置 theme( axis.line = element_blank(), axis.text.x = element_text(size=14, margin=margin(b=10), colour="black"), axis.text.y = element_text(size=14, margin=margin(l=10), colour="black"), axis.ticks = element_blank(), axis.title = element_text(size=18, face="bold"), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), plot.title = element_text(size=18, hjust=0.5), legend.text = element_text(size=14), legend.title = element_text(size=18), # 调整分面标签样式,和X轴视觉统一 strip.background = element_blank(), strip.text = element_text(size=14, face="bold", margin=margin(b=10)), strip.placement = "outside" ) p
方案2:单轴嵌套分组(适合无分面的场景)
如果需要将所有分组放在同一个X轴区域,可以通过组合Name和City字段生成分组位置,手动添加分组标注实现嵌套X轴效果:
library(ggplot2) library(viridis) # 数据清洗 myData$Transport <- trimws(myData$Transport) # 生成Name+City的交互分组作为X轴位置依据 myData$x_group <- interaction(myData$Name, myData$City, sep = "_") p <- ggplot(myData, aes(x = x_group, y = Time, fill = Transport)) + geom_col(position = position_dodge(width = 0.8), width = 0.7) + scale_fill_viridis(discrete = TRUE) + scale_y_continuous(limits = c(0, 10), breaks = seq(0, 10, by = 1)) + # 自定义X轴刻度,仅显示城市名称 scale_x_discrete(labels = rep(c("Boston", "Seattle"), 3), expand = expansion(add = c(0.5, 0.5))) + labs(x = "City (grouped by Name)", y = "Time", title = "People", fill = "Transport") + # 添加人名分组标注和组分隔线 annotate("text", x = c(1.5, 3.5, 5.5), y = -0.8, label = c("Rick", "Jane", "Ellen"), size = 5, fontface = "bold") + geom_vline(xintercept = c(2.5, 4.5), linetype = "dashed", color = "gray80") + theme( axis.line = element_blank(), axis.text.x = element_text(size=14, margin=margin(b=15), colour="black"), axis.text.y = element_text(size=14, margin=margin(l=10), colour="black"), axis.ticks = element_blank(), axis.title = element_text(size=18, face="bold"), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), plot.title = element_text(size=18, hjust=0.5), legend.text = element_text(size=14), legend.title = element_text(size=18), # 给底部人名标注预留展示空间 plot.margin = margin(b=20) ) p
内容的提问来源于stack exchange,提问作者LT17
相关产品推荐
相关产品推荐

