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

