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

ggplot2绘制多组嵌套分类值折线图,显示双层分类标签

R语言ggplot2绘制带双层嵌套X轴标签的折线图

需求描述

现有不同酒店品牌的客户满意度调查数据,调查问题分为category(大类)和subcategory(子分类)两个层级,不同大类下的子分类数量不一致。需要绘制折线图展示各酒店品牌在每个子分类下的得分,同时在X轴显示大类和子分类两层标签,且保证不同大类间的折线完全连通不截断。

示例数据如下:

hotels = data.frame(category = rep(c("room","room","service","service","overall rating"),each = 3),
                   subcategory = rep(c("comfort","cleanliness","professionalism","promptness","overall rating"),each = 3),
                   brand = rep(c("hotel 1","hotel 2","hotel 3"),times = 5),
                   score = c(6,10,4,7,9,2,6,9,5,9,7,3,6,8,3))

已尝试的无效方案

方案1:直接以子分类为X轴绘图

# 因子化变量保证绘图时顺序正确
hotels$category = factor(hotels$category, levels = c("room","service","overall rating"))
hotels$subcategory = factor(hotels$subcategory, levels =c("comfort","cleanliness","professionalism","promptness","overall rating"))

# 绘图
library(dplyr)
library(ggplot2)

p = hotels %>%
  ggplot(aes(x=subcategory, y=score, group=brand, color=brand)) +
  geom_line() +
  geom_point()

p

存在问题:仅能显示子分类标签,无法体现子分类的大类归属。

方案2:分面实现双层标签

p = hotels %>%
  ggplot(aes(x=subcategory, y=score, group=brand, color=brand)) +
  geom_line() +
  geom_point() +
  facet_grid(~category,
             scales = "free_x",
             space = "free_x",
             switch = "x") +
  theme(panel.spacing = unit(0, units = "cm"),
                             strip.placement = "outside")

p

存在问题:分面会导致不同大类间的折线被截断,不符合需求。

无法适配的其他公开方案

  • 跨分面绘制连接线方案:该方案适配X轴为连续型变量、各分面X值相同的场景,本次需求X轴是分类变量,各分面包含不同子分类,无法适配
  • 嵌套分组变量的多行轴标签方案:该方案仅适用于柱状图,本次需求为折线图,无法适配
  • 嵌套分类轴图表方案:该方案仅适用于点图,实测后得到和分面方案一样的折线断裂结果,无法适配

最终实现方案

通过ggh4x包的guide_axis_nested()函数实现嵌套轴标签,既可以保留完整连通的折线,又能显示双层分类标签,完整代码如下:

# 数据
hotels = data.frame(category = rep(c("room","room","service","service","overall rating"),
                                   each = 3),
                    subcategory = rep(c("comfort","cleanliness","professionalism",
                                        "promptness","overall rating"),each = 3),
                    brand = rep(c("hotel 1","hotel 2","hotel 3"),times = 5),
                    score = c(6,10,4,7,9,2,6,9,5,9,7,3,6,8,3))

# 向数据集新增拼接变量
hotels$paste = paste0(hotels$subcategory, "&", hotels$category)

# 绘图
library(dplyr)
library(ggplot2)
library(ggh4x)
library(forcats)
p = hotels %>%
# 使用forcats的mutate函数重排分类顺序
  mutate(paste = fct_relevel(paste, 
                            "comfort&room", "cleanliness&room", "professionalism&service", 
                            "promptness&service", "overall rating&overall rating")) %>%
# X轴为重排后的拼接变量
  ggplot(aes(x=paste, 
             y=score, group=brand, color=brand)) +
  geom_line() +
  geom_point() +
  guides(x = ggh4x::guide_axis_nested(delim = "&"))

p

内容的提问来源于stack exchange,提问作者user17037763

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:09:02