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

