如何在不改变viridis scale的情况下按大小重排桑基图节点
桑基图节点排序与Viridis色阶保持问题解决思路
问题核心
需要在不改变Viridis色阶明暗顺序的前提下,将桑基图第一层级(Method_Group)的节点按流量从大到小排列,但当前绘图后颜色未遵循Viridis标准明暗格式。
问题原因
- 手动指定的
node因子层级未结合实际流量大小,节点排序不符合需求 geom_rect部分使用fill = label重新触发颜色映射,破坏了原有Viridis色阶的对应关系- 原节点排序逻辑与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
相关产品推荐
相关产品推荐

