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

如何在不改变viridis scale的情况下按大小重排桑基图节点

桑基图节点排序与Viridis色阶保持问题解决思路

问题核心

需要在不改变Viridis色阶明暗顺序的前提下,将桑基图第一层级(Method_Group)的节点按流量从大到小排列,但当前绘图后颜色未遵循Viridis标准明暗格式。

问题原因

  1. 手动指定的node因子层级未结合实际流量大小,节点排序不符合需求
  2. geom_rect部分使用fill = label重新触发颜色映射,破坏了原有Viridis色阶的对应关系
  3. 原节点排序逻辑与Viridis色阶的映射规则不匹配

解决步骤

1. 统计节点流量,生成正确排序的因子层级

先从数据中计算第一层级每个节点的总流量,按降序排列后作为node的因子层级,既满足排序需求,也能让Viridis色阶按此顺序分配颜色:

# 统计第一层级节点的流量(按node分组计数)
node_sizes <- df |>
  filter(x == "Method_Group") |>
  count(node, name = "size") |>
  arrange(desc(size))

# 生成按流量降序的因子层级(先排第一层级节点,再排第二层级)
df$node <- factor(df$node, levels = c(node_sizes$node, unique(df$node[df$x == "Topic"])))

2. 修正绘图代码,统一颜色映射

移除geom_rect中独立的fill映射,改用桑基图层已生成的颜色值,避免破坏Viridis色阶的对应关系:

library(ggsankey)
library(dplyr)
library(ggplot2)

width <- .4

# 基础绘图,绑定Viridis色阶映射
p <- ggplot(df, aes(x = x, next_x = next_x, node = node, next_node = next_node, 
                    fill = node, label = node)) +
  geom_sankey(flow.alpha = 1, node.color = "black", show.legend = FALSE, width = width) +
  theme_void() +
  theme(plot.margin = unit(rep(5.5, 4), "pt")) +
  scale_fill_viridis_d(option = "viridis") # 明确指定标准Viridis色阶

# 获取桑基图的节点数据(包含已分配的Viridis颜色值)
dat <- layer_data(last_plot(), 1) |>
  filter(x == 1 + width / 2) |> # 定位第一层级节点的位置
  distinct(fill, ymin, ymax, .keep_all = TRUE)

# 复用已有的颜色值绘制矩形,避免重新映射
p <- p +
  geom_rect(data = dat, aes(
    xmin = x - width/2, xmax = x + width/2,
    ymin = ymin, ymax = ymax,
    fill = I(fill) # 直接使用桑基图已生成的颜色
  ), inherit.aes = FALSE) +
  geom_sankey_label(size = 5, color = "black", fill = "white") +
  guides(fill = "none")

p

3. 关键说明

  • 用实际流量统计结果生成因子层级,确保第一层级节点按从大到小排列
  • 使用I(fill)直接复用Viridis色阶分配的颜色,避免geom_rect重新触发颜色映射
  • scale_fill_viridis_d(option = "viridis")明确指定标准Viridis色阶,保证明暗顺序完全符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:05:54