R中优化Likert与计数条形图:筛选20个负面反馈最多的类别
解决方案
要实现只展示负面反馈最多的20个类别,核心思路是先筛选目标子集,再基于子集绘图,而非在绘图环节临时处理。以下是修改后的完整代码及说明:
步骤1:计算并筛选前20个负面反馈最多的类别
先从原数据中统计每个类别下"Strongly disagree"和"Disagree"的总数量,排序后提取前20个类别:
library(tidyverse) library(ggstats) library(ggpubr) # 保留原数据生成逻辑 set.seed(42) var_levels <- paste0("Category_", 1:40) likert_levels <- c("Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree") df <- tibble( var = sample(var_levels, 500, replace = TRUE), val = sample(likert_levels, 500, replace = TRUE) ) %>% mutate(across(everything(), as.factor)) # 筛选负面反馈Top20类别 top20_negative <- df %>% mutate(is_negative = val %in% c("Strongly disagree", "Disagree")) %>% group_by(var) %>% summarise(negative_count = sum(is_negative)) %>% arrange(desc(negative_count)) %>% slice_head(n = 20) %>% pull(var) # 生成仅包含目标类别的数据子集 df_filtered <- df %>% filter(var %in% top20_negative)
步骤2:绘制Likert图(基于筛选后子集)
将筛选后的数据转换为gglikert所需的宽格式,同时按负面反馈数量排序类别:
# 转换为宽格式数据 df2_filtered <- df_filtered %>% group_by(var) %>% mutate(row = row_number()) %>% pivot_wider(names_from = var, values_from = val) %>% select(-row) # 绘制Likert图,按负面反馈总数降序排列 v1 <- gglikert(df2_filtered) + aes(y = reorder(.question, .data[[".answer"]] %in% c("Strongly disagree", "Disagree"), FUN = sum, decreasing = TRUE))
步骤3:绘制负面反馈计数条形图
基于筛选子集统计负面反馈数量,直接生成条形图:
v2 <- df_filtered %>% mutate(is_negative = val %in% c("Strongly disagree", "Disagree")) %>% group_by(var) %>% summarise(negative_count = sum(is_negative)) %>% mutate(var = reorder(var, negative_count, decreasing = TRUE)) %>% ggplot(aes(y = var, x = negative_count)) + geom_bar(stat = "identity", fill = "lightgrey") + labs(x = "负面反馈总数")
步骤4:组合两张图表
ggarrange(v1, v2, widths = c(6, 2))
关键改动说明
- 提前筛选子集:避免全量数据导致图表拥挤,聚焦Top20负面类别
- 统一排序逻辑:Likert图和条形图按同一规则排序,保证视觉一致性
- 简化统计逻辑:单独统计负面反馈数量,比原代码的
ifelse写法更直观
内容的提问来源于stack exchange,提问作者Homer Jay Simpson
相关产品推荐
相关产品推荐

