如何在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
相关产品推荐
相关产品推荐

