如何用Plotly R制作含中间预算栏的收支流向桑基图?
Plotly R 实现左收入-中预算-右支出的桑基图
桑基图的核心是节点(nodes)与链接(links)的对应关系,Plotly 里的source和target是节点在nodes列表中的0-based索引(不是名称,也不是R默认的1-based序号),这是最容易踩坑的点。要实现左中右三栏布局,需要手动指定每个节点的水平位置。
1. 定义节点与分组
先把所有要展示的节点按「收入→预算→支出」的顺序列出来,同时给每个节点分配水平位置(x=0:左栏收入,x=0.5:中栏预算,x=1:右栏支出):
library(plotly) # 定义所有节点:收入组(左)→预算组(中)→支出组(右) nodes <- data.frame( name = c( # 收入项(左栏) "工资", "副业收入", "投资收益", # 预算项(中栏) "日常开销预算", "房贷预算", "娱乐预算", # 支出项(右栏) "餐饮", "交通", "房贷还款", "电影", "旅游" ), # 指定每个节点的水平位置:0=左,0.5=中,1=右 x = c(0, 0, 0, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1) )
2. 定义流向链接
links数据框需要包含三个核心字段:
source:起始节点在nodes中的0-based索引target:目标节点在nodes中的0-based索引value:流量金额
示例流向逻辑:工资分配到日常开销和房贷预算,副业收入分配到娱乐预算,投资收益补充娱乐预算;再由各预算项对应到具体支出:
links <- data.frame( # 第一部分:收入→预算的流向 source = c(0, 0, 1, 2), target = c(3, 4, 5, 5), value = c(8000, 5000, 2000, 3000) ) # 第二部分:预算→支出的流向 links <- rbind(links, data.frame( source = c(3, 3, 4, 5, 5), target = c(6, 7, 8, 9, 10), value = c(5000, 3000, 5000, 1500, 3500) ))
3. 绘制桑基图
用plot_ly的sankey类型,传入节点和链接数据,配置样式确保布局整齐:
plot_ly( type = "sankey", arrangement = "snap", # 自动对齐节点,优化布局 node = list( label = nodes$name, x = nodes$x, color = c(rep("#4CAF50", 3), rep("#2196F3", 3), rep("#FF9800", 5)), # 分组配色 pad = 15, # 节点间间距 thickness = 20 # 节点厚度 ), link = list( source = links$source, target = links$target, value = links$value, color = "rgba(200,200,200,0.5)" # 链接半透明,避免遮挡 ) ) %>% layout(title = "收入-预算-支出流向桑基图", font = list(size = 12))
关键注意事项
- 索引是0-based:R语言是1-based,但Plotly桑基图的
source/target必须用从0开始的索引,比如第一个节点「工资」的索引是0,不是1。 - 固定节点位置:通过
node.x指定0/0.5/1,确保收入、预算、支出分别在左、中、右三栏,避免节点顺序混乱。 - 流向逻辑:严格遵循「收入→预算→支出」的二级流向,符合你需要的中间预算栏的展示需求。
内容的提问来源于stack exchange,提问作者Quinten
相关产品推荐
相关产品推荐

