如何用ggplot绘制带独立不知道块的李克特量表水平堆叠条形图
实现思路
- 数据预处理:将「强烈同意」「同意」两类选项的数值转为负数,堆叠后会自动展示在中心0轴左侧;「不同意」「强烈不同意」保留正数,堆叠后展示在中心轴右侧。
- 分图层绘制:单独为「不知道」选项开辟独立的绘制区域,在中心轴右侧的固定偏移位置绘制「不知道」的条形,和态度类选项之间留出明显间隔,避免混淆。
- 坐标轴适配:将X轴的刻度标签替换为绝对值,避免左侧的负数值误导用户,同时保留数值对比的直观性。
完整可运行代码
library(tidyverse) # 导入模拟数据 df <- structure(list(Q = structure(1:3, .Label = c("Q1", "Q2", "Q3"), class = "factor"), SA = c(25, 18, 12), A = c(30, 25, 15), DA = c(25, 20, 25), SDA = c(10, 18, 25), DK = c(10, 19, 23)), row.names = c(NA, -3L), class = "data.frame") # 数据重构为长格式,适配ggplot堆叠条形图要求 df_attitude <- df %>% # 同意类数值转负,用于左侧展示 mutate(across(c(SA, A), ~ -.x)) %>% pivot_longer(cols = -c(Q, DK), names_to = "option", values_to = "cnt") %>% mutate(option = factor(option, levels = c("SA", "A", "DA", "SDA"), labels = c("强烈同意", "同意", "不同意", "强烈不同意"))) # 设定「不知道」区块的起始位置,和态度类选项间隔5个单位 dk_start_x <- max(abs(df_attitude$cnt)) + 5 # 绘图 ggplot() + # 绘制中心分隔线 geom_vline(xintercept = 0, linewidth = 1) + # 绘制态度类堆叠条形 geom_bar(data = df_attitude, aes(x = cnt, y = Q, fill = option), stat = "identity", position = "stack") + # 绘制独立的「不知道」区块 geom_bar(data = df, aes(x = dk_start_x + DK/2, y = Q, width = DK, fill = "不知道"), stat = "identity", alpha = 0.8) + # X轴调整:显示绝对值,适配「不知道」区块宽度 scale_x_continuous(breaks = seq(-60, 60, 20), labels = abs(seq(-60, 60, 20)), expand = c(0, 0), limits = c(-60, dk_start_x + 30)) + # Y轴调整:问题序号从上到下排列 scale_y_discrete(limits = rev) + # 填充色自定义,可按需调整 scale_fill_manual(values = c("强烈同意" = "#2c7fb8", "同意" = "#7fcdbb", "不同意" = "#fc8d59", "强烈不同意" = "#d73027", "不知道" = "#969696"), name = "回答选项") + labs(x = "回答人数", y = "问题") + theme_minimal() + theme(panel.grid = element_blank())
如果需要调整间隔、配色、数值标签,直接修改对应参数即可。
内容的提问来源于stack exchange,提问作者iod
相关产品推荐
相关产品推荐

