ggplot中如何为1-5分问卷数据固定颜色与分值的映射关系
问题描述
我有一组1-5分的同意度问卷数据,需要为不同分组绘制可视化图表,要求颜色与分值固定对应:
- 1分对应深绿色
#0da262 - 2分对应浅绿色
#62d5a4 - 3分对应灰色
gray - 4分对应浅红色
#e07171 - 5分对应深红色
#d34040
但由于分组样本量较小,部分分组可能缺失1-5中的部分分值(多次运行代码会出现该情况),例如某分组没有分值1的回答,此时不应显示对应深绿色,且必须保证分值与颜色的对应关系始终固定(即5始终对应深红色、1始终对应深绿色等)。现有如下ggplot代码,应如何调整实现该需求?
原代码:
library(tidyverse) library(ggplot2) n <- 15 test_df <- data.frame(varA = sample(1:5, size=n, replace=TRUE), #varB = sample(1:5, size=n, replace=TRUE), grp = sample(c("A", "B", "C"), size = n, replace=TRUE)) palette <- c("#0da262", "#62d5a4", "gray", "#e07171", "#d34040") test_df %>% pivot_longer(cols = starts_with("var")) %>% group_by(grp, name) %>% count(value) %>% mutate(percent = 1/sum(n)*n) %>% ggplot(aes(x = name, y = percent, fill = as.factor(value))) + geom_col(position = "fill") + coord_flip() + scale_fill_manual(values = palette, drop = FALSE) + labs(fill = "Value")
解决方案
核心是将颜色 palette 定义为命名向量,让每个颜色和对应的分值直接绑定,同时通过指定因子水平、保留drop = FALSE确保图例完整且颜色映射不混乱。
调整要点
- 将颜色向量改为命名向量,明确绑定每个分值与对应颜色
- 强制将
value转换为包含完整1-5水平的因子,避免缺失值导致因子水平丢失 - 优化百分比计算逻辑(可选,让代码更直观)
修改后的完整代码:
library(tidyverse) library(ggplot2) n <- 15 test_df <- data.frame(varA = sample(1:5, size=n, replace=TRUE), #varB = sample(1:5, size=n, replace=TRUE), grp = sample(c("A", "B", "C"), size = n, replace=TRUE)) # 定义命名颜色向量,直接绑定分值与对应颜色 palette <- c( "1" = "#0da262", "2" = "#62d5a4", "3" = "gray", "4" = "#e07171", "5" = "#d34040" ) test_df %>% pivot_longer(cols = starts_with("var")) %>% group_by(grp, name) %>% count(value) %>% mutate(percent = n / sum(n)) %>% # 更直观的百分比计算方式 mutate(value = factor(value, levels = 1:5)) %>% # 指定完整的1-5因子水平 ggplot(aes(x = name, y = percent, fill = value)) + geom_col(position = "fill") + coord_flip() + scale_fill_manual(values = palette, drop = FALSE) + # 保留图例所有选项 labs(fill = "同意度分值")
效果说明
- 命名向量
palette确保无论数据是否缺失分值,颜色与分值的对应关系始终固定 - 指定因子水平
1:5让ggplot能识别所有可能的分值,避免因缺失值导致颜色错位 drop = FALSE让图例始终显示1-5分的完整选项,但缺失分值的分组不会在图表中生成对应颜色的柱子- 百分比计算逻辑优化后,代码可读性更强,结果与原代码一致
内容的提问来源于stack exchange,提问作者D. Studer
相关产品推荐
相关产品推荐

