You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:用ggplot绘制混合变量堆叠条形图(多调色板+分类图例)

我希望使用ggplot绘制堆叠条形图,横轴为变量,这些变量的响应类型不同:部分为Y/N二分类、部分为Old/Young二分类、还有部分为0-5的Likert量表。需为不同类型的变量分配不同的调色板,并添加能体现不同调色板/变量类型的图例。附上示例数据代码,恳请协助实现。

X1<-c("N","N","N","N","Y","N","Y","N","N","N","N","N","Y","N","N","Y","N","N","N","Y","N","Y","Y","N","N","Y","Y","Y","N","N","N","N","N","N","N","N","Y","N","Y","N","N","N","N","Y","N","N","Y","N","Y","Y","N","Y","N","N")
X2 <-c("N","N","N","N","Y","N","Y","N","N","N","N","N","Y","N","N","Y","N","N","N","Y","N","Y","Y","N","N","Y","Y","Y","N","N","N","N","N","N","N","N","Y","N","Y","N","N","N","N","Y","N","N","Y","N","Y","Y","N","Y","N","N")
X3<-c(1,1,0,1,2,0,0,0,0,0,1,1,1,2,0,1,2,1,1,0,0,0,4,1,0,0,0,0,1,0,2,0,0,2,1,1,0,0,0,1,1,0,1,0,1,0,1,1,0,1,0,1,1,1)
X4 <-c("YouNg","Old","Old","YouNg","Old","Old","Old","YouNg","YouNg","YouNg","Old","Old","Old",
       "Old","Old","Old","Old","YouNg","Old","Old","Old","YouNg","YouNg","Old","Old","Old",
       "Old","Old","Old","Old","Old","Old","Old","YouNg","Old","YouNg","Old","YouNg","Old",
       "Old","YouNg","Old","YouNg","YouNg","Old","Old","Old","YouNg","Old","Old","Old","YouNg", "Old", "Old")

Y <- data.frame(X1, X2, X3, X4)
解决方案

核心思路

  • 将宽格式数据转换为长格式,适配ggplot的绘图逻辑
  • 为每个变量标记类型,便于区分调色板
  • 为不同类型变量自定义专属调色板,避免颜色混淆
  • 通过图例分组和辅助标注,清晰展示变量类型与对应颜色的关系

完整代码实现

# 加载依赖包
library(ggplot2)
library(dplyr)
library(tidyr)
library(stringr)

# 用户提供的示例数据
X1<-c("N","N","N","N","Y","N","Y","N","N","N","N","N","Y","N","N","Y","N","N","N","Y","N","Y","Y","N","N","Y","Y","Y","N","N","N","N","N","N","N","N","Y","N","Y","N","N","N","N","Y","N","N","Y","N","Y","Y","N","Y","N","N")
X2 <-c("N","N","N","N","Y","N","Y","N","N","N","N","N","Y","N","N","Y","N","N","N","Y","N","Y","Y","N","N","Y","Y","Y","N","N","N","N","N","N","N","N","Y","N","Y","N","N","N","N","Y","N","N","Y","N","Y","Y","N","Y","N","N")
X3<-c(1,1,0,1,2,0,0,0,0,0,1,1,1,2,0,1,2,1,1,0,0,0,4,1,0,0,0,0,1,0,2,0,0,2,1,1,0,0,0,1,1,0,1,0,1,0,1,1,0,1,0,1,1,1)
X4 <-c("YouNg","Old","Old","YouNg","Old","Old","Old","YouNg","YouNg","YouNg","Old","Old","Old",
       "Old","Old","Old","Old","YouNg","Old","Old","Old","YouNg","YouNg","Old","Old","Old",
       "Old","Old","Old","Old","Old","Old","Old","YouNg","Old","YouNg","Old","YouNg","Old",
       "Old","YouNg","Old","YouNg","YouNg","Old","Old","Old","YouNg","Old","Old","Old","YouNg", "Old", "Old")

Y <- data.frame(X1, X2, X3, X4)

# 1. 数据预处理:宽转长 + 标记变量类型 + 统一响应文本格式
Y_long <- Y %>%
  pivot_longer(cols = everything(), names_to = "variable", values_to = "response") %>%
  mutate(
    # 统一X4的大小写(YouNg转为Young)
    response = ifelse(variable == "X4", str_to_title(response), as.character(response)),
    # 标记变量所属类型
    var_type = case_when(
      variable %in% c("X1", "X2") ~ "Y/N 二分类",
      variable == "X4" ~ "Old/Young 二分类",
      variable == "X3" ~ "0-5 Likert量表"
    )
  ) %>%
  arrange(var_type, response) # 确保堆叠顺序一致

# 2. 自定义分类型调色板
palettes <- list(
  "Y/N 二分类" = c("N" = "#1f77b4", "Y" = "#ff7f0e"),
  "Old/Young 二分类" = c("Old" = "#2ca02c", "Young" = "#d62728"),
  "0-5 Likert量表" = c("0" = "#f8f9fa", "1" = "#e9ecef", "2" = "#dee2e6", "3" = "#ced4da", "4" = "#adb5bd", "5" = "#6c757d")
)
combined_palette <- unlist(palettes) # 合并为ggplot可用的向量

# 3. 绘制堆叠条形图
ggplot(Y_long, aes(x = variable, fill = interaction(response, var_type, sep = " - "))) +
  geom_bar(position = "fill") + # 绘制百分比堆叠图
  scale_fill_manual(
    values = combined_palette,
    name = "响应类别",
    labels = function(x) gsub("(.*) - (.*)", "\\1", x), # 拆分图例标签,只显示响应值
    guide = guide_legend(
      ncol = 1,
      keyheight = unit(0.8, "cm"),
      override.aes = list(size = 0.5)
    )
  ) +
  # 添加变量类型的顶部标注
  annotate("text", x = 1.5, y = 1.05, label = "Y/N 二分类", size = 4, fontface = "bold") +
  annotate("text", x = 3, y = 1.05, label = "Old/Young 二分类", size = 4, fontface = "bold") +
  annotate("text", x = 4, y = 1.05, label = "0-5 Likert量表", size = 4, fontface = "bold") +
  # 调整坐标轴与主题
  labs(y = "比例", x = "变量") +
  theme_minimal() +
  theme(
    legend.position = "right",
    axis.text.x = element_text(angle = 45, hjust = 1),
    plot.margin = margin(t = 20, r = 20, b = 20, l = 20)
  )

关键细节说明

  1. 数据转换:使用pivot_longer将多列变量合并为"变量-响应"的长格式,同时统一X4的文本格式,避免因大小写导致的类别拆分。
  2. 调色板设计:为三类变量分别设置差异化色系:Y/N用蓝橙对比色、Old/Young用绿红对比色、Likert量表用灰度渐变,直观区分不同变量类型的响应。
  3. 图例优化:通过interaction绑定响应与变量类型,再拆分标签只显示响应值,同时在图表顶部标注变量类型,解决不同类型变量的图例区分问题。
  4. 百分比堆叠:使用position = "fill"将条形图转换为百分比比例,便于跨变量的类别分布对比。

内容的提问来源于stack exchange,提问作者EB3112

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 08:55:22