如何用ggsankeyfier制作y轴为分类变量的桑基图及优化问题
桑基图优化方案(基于ggsankeyfier)
问题描述
使用ggsankeyfier绘制客户年度类别流动桑基图时,遇到两个问题:
- 需手动创建冗余的
final_class变量 - 节点默认升序排列,希望按
class顺序(0在底部、3在顶部)排列,但设置y=node会丢失节点宽度
优化方案及代码
核心优化思路
- 移除冗余变量:利用
ggsankeyfier的统计层自动计算节点权重,无需手动构造final_class - 自定义节点排序:将
class转换为有序因子,强制节点按指定顺序排列,同时保留节点宽度
完整优化代码:
library(tidyverse) library(ggsankeyfier) # 生成示例数据 t <- data.frame( client = rep(c('a','b','c','d','e','f','g'), each = 4), year = rep(2021:2024,7), class = sample(0:3, size = 28, replace = T, prob = c(0.6,0.3,0.09,0.1)) ) # 数据预处理:转宽表+将class转为有序因子(控制排序) t_wide <- t %>% pivot_wider(names_from = year, values_from = class) %>% mutate(across(2021:2024, ~ factor(.x, levels = c(0,1,2,3), ordered = TRUE))) # 绘制桑基图 ggplot(t_wide) + aes( x = stage, y = after_stat(weight), # 自动用客户数量作为节点权重,替代final_class group = node, connector = connector, edge_id = edge_id ) + pivot_stages_longer(as.character(2021:2024)) + # 无需指定values_from参数 geom_sankeyedge(aes(fill = node), position = pos, ncp = 1) + geom_sankeynode(aes(fill = node), position = pos) + geom_text( aes(label = str_wrap(node, 20)), position = pos_text, stat = "sankeynode", hjust = 0, cex = 2 ) + theme_minimal()
关键细节说明
- 移除冗余变量:通过
y = after_stat(weight)让stat_sankeynode自动计算节点高度(对应客户数量),完全替代手动创建的final_class变量,简化数据处理步骤 - 节点排序控制:将各年度的
class列转为有序因子,指定levels = c(0,1,2,3),这样绘图时节点会严格按照0(底部)→1→2→3(顶部)的顺序排列,同时节点宽度由对应客户数量自动计算,不会丢失宽度信息
内容的提问来源于stack exchange,提问作者Théodore Targerian
相关产品推荐
相关产品推荐

