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

