ggplot2堆叠条形图与Likert量表前后测原始数据不匹配问题
问题排查与修复方案
核心问题
你的图表比例不符,根源是未按「警局+测试阶段」的分组计算各选项占比,而是默认采用全局统计;另外Likert选项的顺序设置也可能导致堆叠位置与实际选项不匹配。
修复步骤(附可复现代码)
假设你的原始数据结构如下(模拟你的场景):
library(tidyverse) library(ggplot2) # 模拟可复现数据 set.seed(123) df <- tibble( Police_Station = rep(c("A", "B", "C", "D", "E"), each = 12), Test_Phase = rep(c("Before", "After"), each = 6, times = 5), Response = sample(c("强烈反对", "反对", "中立", "同意", "强烈同意"), 60, replace = TRUE) ) # 手动修正C警局Before的中立数据(匹配你说的6人里3个中立) df <- df %>% mutate(Response = ifelse(Police_Station == "C" & Test_Phase == "Before", rep(c("强烈反对", "反对", "中立", "中立", "中立", "同意"), 1), Response))
1. 正确计算分组占比
必须按Police_Station和Test_Phase分组,统计组内各选项的比例:
# 分组统计各选项的数量与占比 df_summary <- df %>% group_by(Police_Station, Test_Phase, Response) %>% summarise(count = n(), .groups = "drop") %>% group_by(Police_Station, Test_Phase) %>% mutate(prop = count / sum(count)) %>% ungroup()
2. 指定Likert选项的堆叠顺序
确保「强烈反对」在顶部,需要把选项设为有序因子,指定从「强烈反对」到「强烈同意」的顺序:
# 设置因子顺序,确保堆叠顺序符合要求 df_summary$Response <- factor(df_summary$Response, levels = c("强烈反对", "反对", "中立", "同意", "强烈同意"), ordered = TRUE)
3. 绘制正确的堆叠条形图
使用position_stack(reverse = TRUE)让第一个因子(强烈反对)显示在堆叠顶部:
ggplot(df_summary, aes(x = Police_Station, y = prop, fill = Response)) + geom_col(position = position_stack(reverse = TRUE)) + facet_wrap(~Test_Phase) + scale_y_continuous(labels = scales::percent_format()) + labs(title = "各警局前后测Likert回答比例", y = "比例", x = "警局", fill = "回答选项") + theme_minimal()
验证要点
- 先打印
df_summary查看C警局Before阶段的中立比例是否为50%,确认统计逻辑正确后再绘图。 - 若仍有问题,检查原始数据中
Response列的类别是否统一(比如有没有拼写错误导致的额外类别)。
内容的提问来源于stack exchange,提问作者EtoiledeMoyenOrient
相关产品推荐
相关产品推荐

