如何在R条形图中用多响应变量设X轴与填充,并添加比例和计数
解决方案
1. 数据预处理(核心步骤)
首先需要把多响应的HNV和IN变量转成长格式,筛选值为1的记录,再合并得到所有有效组合:
library(tidyverse) # 假设你的原始数据集名为df,先转HNV为长格式 hnv_long <- df %>% pivot_longer(cols = starts_with("HNV"), # 匹配所有HNV开头的列 names_to = "HNV_Category", values_to = "HNV_Value") %>% filter(HNV_Value == 1) %>% # 仅保留值为1的记录 select(ID, HNV_Category) # 转IN变量为长格式 in_long <- df %>% pivot_longer(cols = c(Provisioning_IN, Regulating_IN), # 指定IN列名 names_to = "IN_Category", values_to = "IN_Value") %>% filter(IN_Value == 1) %>% select(ID, IN_Category) # 合并两个长表,得到每个ID对应的HNV-IN组合 combined_df <- inner_join(hnv_long, in_long, by = "ID")
2. 绘制计数堆叠条形图(带顶部总计数)
先统计每个HNV类别下的IN计数和总计数,再绘图:
# 统计计数与总计数 count_stats <- combined_df %>% count(HNV_Category, IN_Category) %>% group_by(HNV_Category) %>% mutate(total = sum(n)) %>% # 计算每个HNV的总记录数 ungroup() # 绘图 ggplot(count_stats, aes(x = HNV_Category, y = n, fill = IN_Category)) + geom_bar(stat = "identity") + # 添加顶部总计数,vjust控制垂直位置 geom_text(aes(y = total, label = total), vjust = -0.5, size = 4) + labs(x = "HNV类别", y = "计数", fill = "服务类型") + theme_minimal()
3. 绘制比例堆叠条形图(带顶部总计数)
计算每个HNV类别下的IN比例,再调整geom_text的位置:
# 计算比例 prop_stats <- count_stats %>% mutate(prop = n / total) # 绘图 ggplot(prop_stats, aes(x = HNV_Category, y = prop, fill = IN_Category)) + geom_bar(stat = "identity") + # 总计数放在条形上方,y设为略大于1的位置 geom_text(aes(y = 1.05, label = total), size = 4) + # y轴转为百分比格式 scale_y_continuous(labels = scales::percent_format()) + labs(x = "HNV类别", y = "比例", fill = "服务类型") + theme_minimal()
常见错误排查
你之前用geom_text出错,大概率是这几个原因:
- 没有提前计算总计数,直接在ggplot中动态
sum(n)会因为分组逻辑出错; - 比例图中y轴范围是0-1,总计数的y位置没设对,导致文本被截断或位置错误;
- 数据未正确转长格式,导致HNV或IN的类别对应关系混乱。
如果你的数据中存在HNV类别无对应IN记录的情况,可在统计时用complete()补全缺失组合:
count_stats <- combined_df %>% count(HNV_Category, IN_Category) %>% complete(HNV_Category, IN_Category, fill = list(n = 0)) %>% # 补全所有组合,缺失计数设为0 group_by(HNV_Category) %>% mutate(total = sum(n)) %>% ungroup()
内容的提问来源于stack exchange,提问作者elsich
相关产品推荐
相关产品推荐

