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

如何用R的plotly/networkD3包生成桑基图?数据格式处理咨询

桑基图数据格式解析与转换({plotly}/{networkD3}适用)

三个核心字段的含义

  • source:桑基图里流的起点节点(比如2005_0代表2005年响应类别为0的群体)
  • target:桑基图里流的终点节点(比如2010_1代表2010年响应类别为1的群体)
  • value:从起点节点流向终点节点的样本数量

现有数据转换步骤

你的数据是每个样本(UniqID)在各年份的响应记录,要做年份间的流转分析,需要先把相邻年份的响应配对,再统计每种配对的次数。以下是完整实现代码:

第一步:处理原始数据,生成流转统计

library(dplyr)
library(tidyr)

# 原始数据
df <- data.frame(
  UniqID = rep(c(1:10), times=4), 
  Year = c(rep("2005", times=10), rep("2010", times=10), rep("2015", times=10), rep("2020", times=10)),
  Response_Variable = round(runif(n = 40, min = 0, max = 2), digits = 0)
)

# 转成宽格式:每个ID一行,列对应各年份的响应值
wide_df <- df %>%
  pivot_wider(names_from = Year, values_from = Response_Variable)

# 生成相邻年份的流转配对,并统计数量
flow_data <- bind_rows(
  # 2005 → 2010的流转
  wide_df %>%
    select(UniqID, source_year = `2005`, target_year = `2010`) %>%
    mutate(source = paste0("2005_", source_year), target = paste0("2010_", target_year)),
  # 2010 → 2015的流转
  wide_df %>%
    select(UniqID, source_year = `2010`, target_year = `2015`) %>%
    mutate(source = paste0("2010_", source_year), target = paste0("2015_", target_year)),
  # 2015 → 2020的流转
  wide_df %>%
    select(UniqID, source_year = `2015`, target_year = `2020`) %>%
    mutate(source = paste0("2015_", source_year), target = paste0("2020_", target_year))
) %>%
  count(source, target, name = "value")

第二步:用{networkD3}绘制桑基图

networkD3要求节点用数字ID(0起始),需要先做名称映射:

library(networkD3)

# 提取所有唯一节点
nodes <- data.frame(name = unique(c(flow_data$source, flow_data$target)))

# 给流转数据匹配数字ID
flow_data <- flow_data %>%
  mutate(
    source_id = match(source, nodes$name) - 1,
    target_id = match(target, nodes$name) - 1
  )

# 生成桑基图
sankeyNetwork(
  Links = flow_data,
  Nodes = nodes,
  Source = "source_id",
  Target = "target_id",
  Value = "value",
  NodeID = "name",
  fontSize = 12,
  nodeWidth = 30
)

第三步:用{plotly}绘制桑基图

plotly支持直接用节点名称,无需转数字ID:

library(plotly)

plot_ly(
  type = "sankey",
  node = list(
    label = unique(c(flow_data$source, flow_data$target)),
    pad = 15,
    thickness = 20
  ),
  link = list(
    source = match(flow_data$source, unique(c(flow_data$source, flow_data$target))) - 1,
    target = match(flow_data$target, unique(c(flow_data$source, flow_data$target))) - 1,
    value = flow_data$value
  )
) %>%
  layout(title = "响应类别年份流转桑基图")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:45:56