R语言绘制Likert Scale图:运行代码后图表空白问题排查
问题描述
我想要绘制Likert量表数据图,横轴为百分比,纵轴为条目(Item),同时在每个条形中间显示百分比数值。但运行下方代码后图表完全空白,仅显示坐标轴标签。
Item <- c("EO1_PS", "EO1_OS", "EO2_PS", "EO2_OS") SA <- c(0, 36, 0, 27) A <- c(0, 64, 0, 73) N <- c(0, 0, 0, 0) D <- c(0, 0, 0, 0) SD <- c(0, 0, 0, 0) NAP <- c(100, 0, 100, 0) # Creating Data Frame df <- data.frame(Item, SA, A, N, D, SD, NAP) print(df) df <- df %> rename( "Strongly Agree" = SA, "Agree" = A, "Neutral" = N, "Disagree" = D, "Strongly Disagree" = SD, "Not Applicable" = NAP ) likert <- df %> gather(response, percent, -Item) likert ind_order <- likert %> filter(response == "Not Applicable") %> arrange(desc(percent)) lik <- likert %> mutate(Item = factor(Item, levels = ind_order, ordered = TRUE)) %> mutate(response = factor(response, levels = c("Strongly Agree", "Agree", "Neutral", "Disagree", "Strongly Disagree", "Not Applicable"), ordered = TRUE, labels = c("Strongly Agree", "Agree", "Neutral", "Disagree", "Strongly Disagree", "Not Applicable") )) %> mutate(percent = ifelse(response %in% c("Strongly Agree", "Agree", "Neutral", "Disagree", "Strongly Disagree", "Not Applicable"), percent)) # Plot gg <- ggplot() gg <- gg + geom_hline(yintercept = 0) gg <- gg + geom_text( data = filter(lik, percent > 0), aes(x = Item, y = percent, group = response, label = paste(percent * 100, "%")), position = "stack", hjust = 1, size = 2.5, color = "white" ) gg <- gg + scale_x_discrete(expand = c(0, .75)) gg <- gg + scale_fill_manual( values = c("#4393c3", "#92c5de", "#b2182b", "gray"), drop = FALSE ) gg <- gg + scale_y_continuous( expand = c(0, .10), breaks = seq(.35, 1, .25), limits = c(.35, .95) ) gg <- gg + coord_flip() gg <- gg + theme_bw() gg <- gg + theme(axis.ticks = element_blank()) gg <- gg + theme(panel.border = element_blank()) gg <- gg + theme(panel.grid.major.y = element_blank()) gg <- gg + theme(panel.grid = element_blank()) gg
错误分析
- 管道符不完整:所有
%>都应为%>%,导致数据处理流程完全失效 - 缺失条形图层:仅添加了水平线和文本图层,没有绘制条形的
geom_col/geom_bar,因此看不到核心的条形元素 - 数值与坐标轴范围不匹配:数据中
percent是整数(如36、100),但scale_y_continuous设置的范围是0.35-0.95,数值完全不在可见区间内 - 因子水平设置错误:
ind_order是筛选后的数据框,不能直接作为Item的因子水平,需提取其中的Item列 - 填充色数量不匹配:
scale_fill_manual仅提供4种颜色,但response有6个类别,颜色数量不足 - 文本位置逻辑错误:
coord_flip交换坐标轴后,geom_text的x/y映射和位置调整逻辑混乱,且未使用堆叠位置对齐文本
修正后的代码
library(tidyverse) # 原始数据 Item <- c("EO1_PS", "EO1_OS", "EO2_PS", "EO2_OS") SA <- c(0, 36, 0, 27) A <- c(0, 64, 0, 73) N <- c(0, 0, 0, 0) D <- c(0, 0, 0, 0) SD <- c(0, 0, 0, 0) NAP <- c(100, 0, 100, 0) # 创建数据框并重命名列 df <- data.frame(Item, SA, A, N, D, SD, NAP) %>% rename( "Strongly Agree" = SA, "Agree" = A, "Neutral" = N, "Disagree" = D, "Strongly Disagree" = SD, "Not Applicable" = NAP ) # 转换为长格式数据 likert <- df %>% gather(response, percent, -Item) # 设置Item的排序规则(按Not Applicable的百分比降序) ind_order <- likert %>% filter(response == "Not Applicable") %>% arrange(desc(percent)) %>% pull(Item) # 提取Item列作为因子水平 # 数据预处理:转换因子类型,将百分比转为小数 lik <- likert %>% mutate(Item = factor(Item, levels = ind_order, ordered = TRUE)) %>% mutate(response = factor(response, levels = c("Strongly Agree", "Agree", "Neutral", "Disagree", "Strongly Disagree", "Not Applicable"), ordered = TRUE )) %>% mutate(percent = percent / 100) # 转为小数适配坐标轴范围 # 绘制图表 ggplot(lik, aes(x = Item, y = percent, fill = response)) + geom_col(position = "stack") + # 添加堆叠条形图层 geom_text( data = filter(lik, percent > 0), aes(label = paste0(round(percent * 100), "%")), position = position_stack(vjust = 0.5), # 文本居中显示在条形内 size = 2.5, color = "white" ) + scale_fill_manual( values = c("#4393c3", "#92c5de", "#fddbc7", "#d6604d", "#b2182b", "gray"), # 匹配6个响应类别的颜色 drop = FALSE ) + scale_y_continuous( expand = c(0, 0), breaks = seq(0, 1, 0.25), limits = c(0, 1), labels = scales::percent_format() # 自动生成百分比坐标轴标签 ) + coord_flip() + theme_bw() + theme( axis.ticks = element_blank(), panel.border = element_blank(), panel.grid = element_blank() ) + labs(x = "条目", y = "百分比")
关键修改说明
- 补全所有管道符
%>%,确保数据处理流程正常运行 - 添加
geom_col(position = "stack")绘制核心的堆叠条形 - 将百分比数值转为小数,让数据适配0-1的坐标轴范围
- 用
pull(Item)提取排序后的条目列表,修正Item的因子水平设置 - 补充
scale_fill_manual的颜色数量,匹配所有6个响应类别 - 调整
geom_text的位置为position_stack(vjust = 0.5),让文本居中显示在条形内部 - 使用
scales::percent_format()自动生成百分比坐标轴标签,简化格式设置
内容的提问来源于stack exchange,提问作者Aydan Pakta
相关产品推荐
相关产品推荐

