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
相关产品推荐
相关产品推荐

