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

如何在ggplot中实现自定义宽高的比例堆叠矩形可视化?

解决方案

要实现你需要的比例矩阵图,核心是用**连续X轴配合geom_rect**来精确控制每个矩形的位置、宽度和高度,避免离散轴带来的间距问题,同时确保每个分类的堆叠高度始终为1。

步骤1:重新整理数据

先计算每个分类在X轴上的起始/结束位置,以及每个变量(v1/v2)对应的Y轴范围:

library(tidyverse)

# 原始数据
cat <- c("A","B","C","D")
v1 <- c(1,3,6,2)
v2 <- c(3,3,10,1)
df <- data.frame(cat,v1,v2)

# 计算比例&坐标范围
df_rect <- df %>%
  # 计算分类内总和、v1占比
  group_by(cat) %>%
  mutate(sum_cat = v1 + v2,
         prop_v1 = v1 / sum_cat) %>%
  ungroup() %>%
  # 计算分类占总总和的比例
  mutate(prop_cat = sum_cat / sum(sum_cat)) %>%
  # 计算每个分类在X轴的起始/结束位置
  arrange(cat) %>%
  mutate(x_start = c(0, cumsum(prop_cat)[-n()]),
         x_end = x_start + prop_cat) %>%
  # 拆分v1和v2的Y轴范围
  pivot_longer(
    cols = c(prop_v1),
    names_to = "var",
    values_to = "prop"
  ) %>%
  # 生成v1的Y坐标(0到prop_v1)
  mutate(var = "v1",
         ymin = 0,
         ymax = prop) %>%
  # 合并v2的Y坐标(prop_v1到1)
  bind_rows(
    df %>%
      group_by(cat) %>%
      mutate(sum_cat = v1 + v2,
             prop_v1 = v1 / sum_cat) %>%
      ungroup() %>%
      mutate(prop_cat = sum_cat / sum(sum_cat)) %>%
      arrange(cat) %>%
      mutate(x_start = c(0, cumsum(prop_cat)[-n()]),
             x_end = x_start + prop_cat) %>%
      mutate(var = "v2",
             ymin = prop_v1,
             ymax = 1)
  )

步骤2:绘制图形

用geom_rect绘制每个矩形,同时设置X轴标签对应分类:

ggplot(df_rect) +
  # 绘制矩形,白色边框区分
  geom_rect(aes(xmin = x_start, xmax = x_end, 
                ymin = ymin, ymax = ymax, 
                fill = var),
            color = "white") +
  # 设置X轴刻度在每个分类的中间位置,标签为分类名称
  scale_x_continuous(
    breaks = df_rect %>% distinct(cat, x_start, prop_cat) %>% mutate(mid = x_start + prop_cat/2) %>% pull(mid),
    labels = df_rect %>% distinct(cat) %>% pull(cat)
  ) +
  # Y轴显示百分比
  scale_y_continuous(labels = scales::percent_format()) +
  # 设置标签和主题
  labs(x = "分类变量", y = "分类内占比", fill = "变量类型") +
  theme_minimal()

为什么之前的方法有问题?

  • 堆叠条形图用离散X轴时,width参数是相对于离散刻度的相对宽度,无法完全消除分类间的默认间距,且宽度的比例关系会被离散轴的间距干扰。
  • geom_tile默认基于离散坐标,直接设置height=prop.v无法让每个分类的堆叠高度统一为1,因为离散Y轴的刻度间隔是固定的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:54:52