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

如何在ggplot2中复现基于sfo包绘制的桑基图?

问题

已通过plotly的sankey_ly函数生成2019年旧金山国际机场(SFO)联合航空乘客分布的桑基图,现需在ggplot2中复现该图,但自行编写的ggplot2代码无法正常运行,寻求技术协助。

原Plotly桑基图实现代码

library(sfo)

# 数据预处理片段
sfo_passengers %>%
  filter(activity_period == max(activity_period)) %>%
  group_by(activity_type_code, geo_region) %>%
  summarise(total = sum(passenger_count), .groups = "drop")

# 生成桑基图核心代码
sfo_passengers %>% 
  filter(operating_airline == "United Airlines",
         activity_period >= 201901 & activity_period < 202001) %>%
  mutate(terminal = ifelse(terminal == "International", "international", terminal)) %>%
  group_by(operating_airline,activity_type_code, geo_summary, geo_region,  terminal) %>%
  summarise(total = sum(passenger_count), .groups = "drop") %>%
  sankey_ly(cat_cols = c("operating_airline", "terminal","geo_summary", "geo_region", "activity_type_code"), 
            num_col = "total",
            title = "Dist. of United Airlines Passengers at SFO During 2019")

# 添加注释
p <- plotly::last_plot()
plotly::add_annotations(p, c("Terminals", "Domestic/Int"), x = c(0.2, 0.5), y = c(1, 1), showarrow = FALSE)

无效的ggplot2尝试代码

# Load required libraries
library(ggplot2)
library(dplyr)

sfo_passengers_filtered <- sfo_passengers %>% 
  filter(activity_period == max(activity_period)) %>%
  group_by(activity_type_code, geo_region) %>%
  summarise(total = sum(passenger_count), .groups = "drop")

sfo_passengers_united <- sfo_passengers %>% 
  filter(operating_airline == "United Airlines",
         activity_period >= 201901 & activity_period < 202001) %>%
  mutate(terminal = ifelse(terminal == "International", "international", terminal)) %>%
  group_by(operating_airline,activity_type_code, geo_summary, geo_region,  terminal) %>%
  summarise(total = sum(passenger_count), .groups = "drop")

# Create the plot
ggplot(data = sfo_passengers_united, aes(x = terminal, y = geo_region, 
                                          fill = activity_type_code, text = paste("Passengers: ", total))) +
  geom_rect(aes(x = terminal, xend = after_scale(terminal), y = geo_region, yend = after_scale(geo_region), 
                fill = activity_type_code, alpha = total), color = "black") +
  geom_text(aes(label = total), size = 3) +
  scale_fill_brewer(palette = "Set1", name = "Activity Type") +
  scale_alpha_continuous(range = c(0.1, 1), guide = FALSE) +
  theme_minimal() +
  theme(legend.position = "bottom") +
  labs(title = "Distribution of United Airlines Passengers at SFO During 2019",
       x = "Terminals",
       y = "Geo Region")
解决方案

ggplot2本身没有原生支持桑基图的函数,需要借助ggalluvial包(专门用于绘制冲积图/桑基图)来实现。以下是可运行的复现代码:

步骤1:安装并加载依赖包

install.packages("ggalluvial")
library(ggalluvial)
library(ggplot2)
library(dplyr)
library(sfo)

步骤2:数据预处理(复用已有逻辑)

sfo_passengers_united <- sfo_passengers %>% 
  filter(operating_airline == "United Airlines",
         activity_period >= 201901 & activity_period < 202001) %>%
  mutate(terminal = ifelse(terminal == "International", "international", terminal)) %>%
  group_by(operating_airline, activity_type_code, geo_summary, geo_region, terminal) %>%
  summarise(total = sum(passenger_count), .groups = "drop")

步骤3:用ggalluvial绘制桑基图

ggplot(sfo_passengers_united,
       aes(y = total,
           axis1 = operating_airline, axis2 = terminal, axis3 = geo_summary,
           axis4 = geo_region, axis5 = activity_type_code)) +
  # 绘制桑基图的流
  geom_alluvium(aes(fill = activity_type_code), width = 1/12) +
  # 绘制每个层级的节点
  geom_stratum(width = 1/12, fill = "white", color = "black") +
  # 添加节点标签
  geom_text(stat = "stratum", aes(label = after_stat(stratum))) +
  # 设置层级名称
  scale_x_discrete(limits = c("Airline", "Terminal", "Domestic/Int", "Region", "Activity"),
                   expand = c(0.05, 0.05)) +
  scale_fill_brewer(palette = "Set1", name = "Activity Type") +
  theme_minimal() +
  theme(legend.position = "bottom") +
  labs(title = "Distribution of United Airlines Passengers at SFO During 2019",
       y = "Passenger Count")

代码说明

  • axis1到axis5对应plotly桑基图中的层级顺序:航空公司→航站楼→境内/境外→地区→活动类型
  • geom_alluvium负责绘制各节点间的流,宽度由乘客数(total)决定
  • geom_stratum绘制每个层级的矩形节点
  • geom_text为每个节点添加标签,after_stat(stratum)自动提取分类文本
  • scale_x_discrete自定义各层级的显示名称,和plotly中的注释对应

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 01:35:54