如何用ggplot实现属性名称置于条形图层级上方的布局?
解决方案:调整属性标签至层级组上方
单组布局实现
通过手动计算每个属性组的中心位置,将属性标签添加到对应层级组的右侧(因coord_flip后布局变化),同时保留层级作为y轴标签:
library(tidyverse) df <- tribble( ~group, ~level, ~value, ~attribute, "g1", 0, 1, "attr1", "g1", 1, 2, "attr1", "g1", 0, 0, "attr2", "g1", 14, 3, "attr2", "g1", 16, 4, "attr2" ) # 排序并生成每个条目的y轴位置 df <- df %>% arrange(attribute, level) %>% mutate(y_pos = row_number()) # 计算每个属性组的中心位置 attr_centers <- df %>% group_by(attribute) %>% summarise(center_y = mean(y_pos), .groups = "drop") ggplot(df, aes(x = value, y = y_pos)) + geom_bar(stat = "identity", width = 0.8) + # 添加属性标签到组右侧 geom_text(data = attr_centers, aes(x = max(df$value)*1.1, y = center_y, label = attribute), hjust = 0, size = 4, fontface = "bold") + # 设置y轴显示层级 scale_y_continuous(breaks = df$y_pos, labels = df$level, expand = expansion(add = c(1,1))) + ggtitle("Title") + xlab("Marginal utility") + ylab("") + # 扩展x轴范围,避免标签被截断 coord_cartesian(xlim = c(0, max(df$value)*1.2), clip = "off") + # 右侧留足够空间放标签 theme(plot.margin = margin(r = 50))
双组布局实现
基于单组逻辑,通过facet_wrap实现双组,并为每个分组单独计算属性标签位置:
library(tidyverse) df <- tribble( ~group, ~level, ~value, ~attribute, "g1", 0, 1, "attr1", "g1", 1, 2, "attr1", "g1", 0, 0, "attr2", "g1", 14, 3, "attr2", "g1", 16, 4, "attr2", "g2", 0, 3, "attr1", "g2", 1, 1, "attr1", "g2", 0, 0, "attr2", "g2", 14, 2, "attr2", "g2", 16, 3, "attr2" ) # 按分组排序并生成y轴位置 df <- df %>% group_by(group) %>% arrange(attribute, level) %>% mutate(y_pos = row_number()) %>% ungroup() # 计算每个分组内属性组的中心位置和最大值 attr_centers <- df %>% group_by(group, attribute) %>% summarise(center_y = mean(y_pos), max_val = max(value), .groups = "drop") ggplot(df, aes(x = value, y = y_pos)) + geom_bar(stat = "identity", width = 0.8) + # 为每个分组添加属性标签 geom_text(data = attr_centers, aes(x = max_val*1.1, y = center_y, label = attribute), hjust = 0, size = 4, fontface = "bold") + scale_y_continuous(breaks = df$y_pos, labels = df$level, expand = expansion(add = c(1,1))) + facet_wrap(~group, ncol = 2) + ggtitle("Title") + xlab("Marginal utility") + ylab("") + coord_cartesian(xlim = c(0, max(df$value)*1.2), clip = "off") + theme(plot.margin = margin(r = 50))
备选方案:使用ggh4x嵌套分面
利用ggh4x的facet_nested将属性作为嵌套层级,调整strip位置到层级上方:
library(tidyverse) library(ggh4x) df <- tribble( ~group, ~level, ~value, ~attribute, "g1", 0, 1, "attr1", "g1", 1, 2, "attr1", "g1", 0, 0, "attr2", "g1", 14, 3, "attr2", "g1", 16, 4, "attr2", "g2", 0, 3, "attr1", "g2", 1, 1, "attr1", "g2", 0, 0, "attr2", "g2", 14, 2, "attr2", "g2", 16, 3, "attr2" ) ggplot(df, aes(x = value, y = level)) + geom_bar(stat = "identity") + facet_nested(group ~ attribute, scales = "free_y", space = "free_y") + coord_flip() + ggtitle("Title") + xlab("Marginal utility") + ylab("") + theme(strip.placement = "outside", strip.text.y = element_text(angle = 0), axis.text.y = element_text(margin = margin(r = 20)))
内容的提问来源于stack exchange,提问作者Olivier Cailloux
相关产品推荐
相关产品推荐

