You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:15:32