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

如何解决ggplotly中ggsankey桑基图节点固定与hover问题?

问题背景

我有按年份、车型维度统计的销售数据,目前已基于ggsankey包实现桑基图可视化,存在两个待解决问题:

  • 需要将车型B始终固定在图表最底部,不受各年份该车型销售额数值变化的影响
  • ggplot生成的静态图通过ggplotly转换为交互式版本时,hover悬浮提示未展示销售额、年份相关信息

原有实现代码

df <- data.frame (model  = c("A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J"),
 Year = c(2015,2015,2015,2015,2015,2015,2015,2015,2015,2015,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2018,2018,2018,2018,2018,2018,2018,2018,2018,2018,2019,2019,2019,2019,2019,2019,2019,2019,2019,2019,2020,2020,2020,2020,2020,2020,2020,2020,2020,2020),
                  sales = c(450,678,456,344,984,456,234,244,655,789,234,567,234,567,232,900,1005,1900,450,345,567,235,456,345,144,333,555,777,111,444,222,223,445,776,331,788,980,1003,456,434,345,2222,3456,456,678,8911,4560,4567,4566,5555,6666,7777,8888,1233,1255,5677,3411,2344,6122,4533))

install.packages("remotes")
#remotes::install_github("davidsjoberg/ggsankey")
library(ggsankey)
library(tidyverse)

plot <- ggplot(df, aes(x = Year,
               node = model,
               fill = model,
               value = sales)) +
  geom_sankey_bump(space = 0, type = "alluvial", color = "transparent", smooth = 15) +
  scale_fill_viridis_d(option = "A", alpha = .8) +
  theme_sankey_bump(base_size = 16) 

ggplotly(plot) 

示例效果图

解决方法

1. 固定车型B在图表最底部

geom_sankey_bump默认会按每个年份的数值大小排序堆叠车型,要固定B的位置,只需要提前把model列转为因子,将B设置为最后一个因子水平即可——绘图时堆叠顺序从下到上对应因子水平从最后一位到第一位,B放在最后一个水平就会始终显示在最底部,不受销售额数值波动影响。

2. 修复ggplotly悬浮提示缺失信息

默认情况下geom_sankey_bump的图层美学映射没有包含hover需要的自定义字段,只需要在aes()中新增text参数,拼接需要展示的年份、车型、销售额信息,再在调用ggplotly()时指定tooltip = "text",就能让悬浮提示正常展示所需字段。

修正后完整代码

df <- data.frame (model  = c("A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J","A","B","C","D","E","F","G","H","I","J"),
 Year = c(2015,2015,2015,2015,2015,2015,2015,2015,2015,2015,2016,2016,2016,2016,2016,2016,2016,2016,2016,2016,2017,2017,2017,2017,2017,2017,2017,2017,2017,2017,2018,2018,2018,2018,2018,2018,2018,2018,2018,2018,2019,2019,2019,2019,2019,2019,2019,2019,2019,2019,2020,2020,2020,2020,2020,2020,2020,2020,2020,2020),
                  sales = c(450,678,456,344,984,456,234,244,655,789,234,567,234,567,232,900,1005,1900,450,345,567,235,456,345,144,333,555,777,111,444,222,223,445,776,331,788,980,1003,456,434,345,2222,3456,456,678,8911,4560,4567,4566,5555,6666,7777,8888,1233,1255,5677,3411,2344,6122,4533))

library(ggsankey)
library(tidyverse)
library(plotly)

# 处理因子顺序,将B放在最后一个水平,固定在图表最底部
df <- df %>%
  mutate(model = factor(model, levels = c(setdiff(unique(model), "B"), "B")))

plot <- ggplot(df, aes(x = Year,
               node = model,
               fill = model,
               value = sales,
               # 自定义悬浮提示展示内容
               text = paste0("年份: ", Year,
                             "<br>车型: ", model,
                             "<br>销售额: ", sales))) +
  geom_sankey_bump(space = 0, type = "alluvial", color = "transparent", smooth = 15) +
  scale_fill_viridis_d(option = "A", alpha = .8) +
  theme_sankey_bump(base_size = 16) 

# 转换为交互式图,指定使用自定义text作为悬浮提示
ggplotly(plot, tooltip = "text")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:09:23