R语言绘制多层桑基图(Sankey Diagram)及金额标注实现方法
R语言networkD3绘制三层会计业务桑基图(带金额标签)
问题根因
networkD3::sankeyNetwork 不支持分段拼接独立绘制的桑基层级,必须输入全局统一的节点表和链路表:所有跨层级的同名节点(比如两层链路中都出现的交易类型type)必须分配唯一的全局数字ID,链路的source、target字段统一引用这套ID,才能生成连贯的多层流向图。
可直接运行的实现代码
依赖包加载与测试数据
先加载需要的包,构造和目标字段完全匹配的测试样本,实际使用时替换为自己的真实数据即可:
library(networkD3) library(dplyr) # 测试样本(字段匹配:network_name/type/thirdparty/amount) set.seed(123) raw_data <- data.frame( network_name = sample(c("对公结算网", "零售支付网", "内部核算网"), 200, replace = TRUE), type = sample(c("转账支出", "缴费扣款", "收入入账", "退款冲正"), 200, replace = TRUE), thirdparty = sample(c("供应商A", "供应商B", "税务部门", "客户C", "员工账户"), 200, replace = TRUE), amount = round(runif(200, 100, 50000), 2) )
数据格式转换(核心步骤)
分别聚合两层链路后,统一生成全局节点表,替换链路的source、target为全局ID:
# 聚合第一层链路:交易网络 -> 交易类型 link_layer1 <- raw_data %>% group_by(source_name = network_name, target_name = type) %>% summarise(value = sum(amount), .groups = "drop") # 聚合第二层链路:交易类型 -> 第三方主体 link_layer2 <- raw_data %>% group_by(source_name = type, target_name = thirdparty) %>% summarise(value = sum(amount), .groups = "drop") # 合并两层链路,提取所有唯一节点生成全局节点表 all_links <- bind_rows(link_layer1, link_layer2) global_nodes <- data.frame( name = unique(c(all_links$source_name, all_links$target_name)) ) # 链路表的source/target转为节点表对应的0起始索引(networkD3强制要求) all_links$source <- match(all_links$source_name, global_nodes$name) - 1 all_links$target <- match(all_links$target_name, global_nodes$name) - 1 # 生成链路的金额标签(支持千分位格式化) all_links$link_label <- paste0("交易总金额:¥", format(all_links$value, big.mark = ",", scientific = FALSE))
绘图
sankeyNetwork( Links = all_links, Nodes = global_nodes, Source = "source", Target = "target", Value = "value", NodeID = "name", LinkGroup = "source_name", fontSize = 12, nodeWidth = 22, nodePadding = 16, sinksRight = FALSE, LinkLabel = "link_label", # 鼠标悬浮链路时显示对应金额 margin = list(top = 10, right = 10, bottom = 10, left = 10) )
适配调整说明
- 如果需要将金额标签固定显示在链路/节点上而非悬浮触发,可以通过
htmlwidgets::onRender注入原生D3代码实现标签定位,不需要修改底层数据结构。 - 如果出现交易类型节点重复显示的问题,检查原始数据中
type字段是否存在多余空格、大小写不一致等情况,全局节点匹配是严格按字符串匹配的,同名节点会自动合并为同一个中间层节点,不会出现链路断裂。 - 金额字段必须按链路聚合求和后传入
Value参数,桑基图的链路宽度会和金额大小成正比,符合会计业务金额流向的展示逻辑。
内容的提问来源于stack exchange,提问作者Tarek Atassi
相关产品推荐
相关产品推荐

