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

如何用R的plotly绘制含缺失值节点的跨年度客户分组桑基图

实现方案

1 依赖包加载

优先使用data.table处理数据,适配你的大体量数据场景,运算效率远高于常规数据框操作:

library(data.table)
library(plotly)

2 数据预处理

2.1 生成跨年度分组映射

按照需求左连接匹配客户ID,未匹配到的客户默认分组赋值为5(无数据):

# 2018→2019流转映射
flow1 <- merge(dt.2018[, .(GPNRPlan, group18 = group)], 
               dt.2019[, .(GPNRPlan, group19 = group)],
               by = "GPNRPlan", all.x = TRUE)
flow1[is.na(group19), group19 := 5]

# 2019→2020流转映射
flow2 <- merge(dt.2019[, .(GPNRPlan, group19 = group)], 
               dt.2020[, .(GPNRPlan, group20 = group)],
               by = "GPNRPlan", all.x = TRUE)
flow2[is.na(group20), group20 := 5]

2.2 生成边统计数据

桑基图需要每条边的起点、终点、流量值三个核心字段,为避免不同年份同分组ID冲突,给节点加上年份前缀:

# 分组编码与名称对应规则
group_label <- c("1" = "最差", "2" = "较差", "3" = "良好", "4" = "优秀", "5" = "无数据")

# 聚合生成18→19的边
edge1 <- flow1[, .(value = .N), by = .(source = group18, target = group19)]
edge1[, source := paste0("2018_", group_label[as.character(source)])]
edge1[, target := paste0("2019_", group_label[as.character(target)])]

# 聚合生成19→20的边
edge2 <- flow2[, .(value = .N), by = .(source = group19, target = group20)]
edge2[, source := paste0("2019_", group_label[as.character(source)])]
edge2[, target := paste0("2020_", group_label[as.character(target)])]

# 合并两段流转的边数据
all_edge <- rbind(edge1, edge2)

2.3 生成节点索引映射

plotly桑基图要求节点用从0开始的数字索引表示,需要先将所有节点名称映射为数字ID:

# 提取所有唯一节点
all_node <- unique(c(all_edge$source, all_edge$target))
node_map <- data.table(label = all_node, id = 0:(length(all_node)-1))

# 把边的节点名称替换为对应索引
all_edge <- merge(all_edge, node_map, by.x = "source", by.y = "label")
setnames(all_edge, "id", "source_id")
all_edge <- merge(all_edge, node_map, by.x = "target", by.y = "label")
setnames(all_edge, "id", "target_id")

3 绘制桑基图

两段流转可以直接在同一张图中展示,会自动生成三层节点,完整呈现2018-2020的全量流转关系:

plot_ly(
  type = "sankey",
  orientation = "h",
  node = list(
    label = node_map$label,
    pad = 15,
    thickness = 20,
    line = list(color = "black", width = 0.5)
  ),
  link = list(
    source = all_edge$source_id,
    target = all_edge$target_id,
    value = all_edge$value
  )
) %>% 
  layout(title = "2018-2020客户分级流转桑基图")

补充说明

  • 全程使用data.table的高效运算逻辑,千万级数据量也可以在几秒内完成处理
  • 如需自定义节点颜色、边透明度,可以在node和link参数中添加color参数调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:57:03