如何在R中针对多主题变量与区域绘制堆叠条形图?
解决堆叠条形图绘制问题的完整方案
首先发现你笔误啦——重复定义了Theme 3,我默认第二个是Theme 4来处理,如果不是的话你调整变量名就行~
第一步:整理数据成tidy格式(ggplot2绘图的最佳格式)
首先我们需要把数据整合到一个数据框里,并且把每个样本的区域、主题、响应(是/否/缺失)对应起来。这里我先补全区域数据(假设10个样本随机分配到4个区域,你可以替换成真实的区域对应关系):
# 定义主题变量(修正重复的Theme3为Theme4) Theme1 <- c(0,1,1,0,0,1,2,2,1,0) Theme2 <- c(0,1,0,1,0,1,2,2,0,1) Theme3 <- c(2,2,0,1,0,1,0,1,1,1) Theme4 <- c(0,0,0,1,1,1,1,2,2,0) # 定义每个样本的区域(这里用随机模拟,你替换成真实的区域分配) set.seed(123) # 保证结果可重复 Region_abb <- sample(c("ESA", "WCA", "MENA", "ASIA"), 10, replace = TRUE) # 构建数据框 df <- data.frame( Region = Region_abb, Theme1 = Theme1, Theme2 = Theme2, Theme3 = Theme3, Theme4 = Theme4 ) # 转换为tidy格式(长格式) library(tidyr) df_long <- pivot_longer(df, cols = starts_with("Theme"), names_to = "Theme", values_to = "Response") # 把响应值替换为标签:0=否,1=是,2=缺失 df_long$Response_label <- factor(df_long$Response, levels = c(0,1,2), labels = c("否", "是", "缺失"))
第二步:统计各区域-主题的响应分布
接下来我们需要统计每个区域下,每个主题的“是/否/缺失”的数量,这样才能绘制堆叠条形图:
library(dplyr) summary_df <- df_long %>% group_by(Region, Theme, Response_label) %>% count() %>% ungroup() %>% group_by(Region, Theme) %>% mutate(percent = n / sum(n) * 100) # 可选:计算百分比,用于标签
第三步:用ggplot2绘制堆叠条形图
现在就可以绘制堆叠条形图了,这里提供两种版本:计数版本和百分比版本,你可以按需选择:
计数堆叠图
library(ggplot2) ggplot(summary_df, aes(x = Region, y = n, fill = Response_label)) + geom_col(position = "stack") + facet_wrap(~Theme) + # 每个主题单独一个子图 labs(title = "各区域主题响应分布(计数)", x = "区域", y = "样本数量", fill = "响应") + theme_bw() + scale_fill_brewer(palette = "Set2")
百分比堆叠图(更适合对比占比)
ggplot(summary_df, aes(x = Region, y = percent, fill = Response_label)) + geom_col(position = "stack") + geom_text(aes(label = paste0(round(percent), "%")), position = position_stack(vjust = 0.5)) + # 添加百分比标签 facet_wrap(~Theme) + labs(title = "各区域主题响应分布(百分比)", x = "区域", y = "占比(%)", fill = "响应") + theme_bw() + scale_fill_brewer(palette = "Set2")
关键问题说明
- 数据格式问题:之前构建矩阵可能出错,是因为ggplot2更适合长格式(tidy)数据,而不是宽格式的矩阵。转换成长格式后,分组统计会更清晰。
- 区域对应关系:你需要确保
Region_abb的长度和主题变量一致(都是10),每个元素对应一个样本的区域。如果你的区域是按组划分(比如每个区域有不同数量的样本),只需要调整Region_abb的取值即可。 - 重复的Theme3:一定要修正这个变量名,不然会覆盖之前的数据,导致结果错误。
内容的提问来源于stack exchange,提问作者BloopFloopy
相关产品推荐
相关产品推荐

