如何在地图上叠加用R(networkD3)制作的迁徙桑基图?
在地图上叠加迁徙桑基图的实现方案
一、R语言实现方案(适配你的现有技术栈)
1. 数据预处理
首先需要清洗数据,匹配国家地理坐标,方便后续和地图结合:
# 加载依赖包 library(tidyverse) library(rnaturalearth) # 获取世界地图数据 library(ggalluvial) # 绘制类桑基的流线 # 清洗示例数据:移除来源国前缀,提取纯国家名 clean_flow_data <- flow1990_data %>% mutate(Origin = str_remove(`Country of Origin`, "Emigrants.from.")) %>% select(Origin, Destination, `Number of Emigrants`) # 获取国家地理数据,提取每个国家的中心坐标 world_countries <- ne_countries(returnclass = "sf") %>% select(name, geometry) # 定义函数:根据国家名获取中心经纬度 get_country_center <- function(country_name) { target <- world_countries %>% filter(name == country_name) if(nrow(target) == 0) return(tibble(lon = NA, lat = NA)) st_centroid(target) %>% st_coordinates() %>% as_tibble() %>% rename(lon = X, lat = Y) } # 给迁徙数据添加来源地、目的地的坐标 flow_with_coords <- clean_flow_data %>% rowwise() %>% mutate( origin_coords = list(get_country_center(Origin)), dest_coords = list(get_country_center(Destination)) ) %>% unnest(c(origin_coords, dest_coords)) %>% rename(lon_origin = lon...5, lat_origin = lat...6, lon_dest = lon...7, lat_dest = lat...8)
2. 静态地图+迁徙流线(类桑基效果)
用ggplot2直接叠加地图和渐变流线,流线宽度对应移民人数,直观展示地理流向:
# 绘制基础地图(聚焦美洲区域,可根据数据调整范围) base_map <- ggplot() + geom_sf(data = world_countries, fill = "#f5f5f5", color = "gray60") + coord_sf(xlim = c(-120, -30), ylim = c(-60, 30)) # 添加迁徙流线、节点 map_with_flow <- base_map + # 渐变流线:曲率模拟桑基图的流畅感 geom_curve( data = flow_with_coords, aes(x = lon_origin, y = lat_origin, xend = lon_dest, yend = lat_dest, size = `Number of Emigrants`, color = Origin), curvature = 0.2, alpha = 0.7 ) + # 来源国节点(红色)、目的地节点(蓝色) geom_point(data = flow_with_coords %>% distinct(Origin, lon_origin, lat_origin), aes(x = lon_origin, y = lat_origin), color = "darkred", size = 3) + geom_point(data = flow_with_coords %>% distinct(Destination, lon_dest, lat_dest), aes(x = lon_dest, y = lat_dest), color = "darkblue", size = 4) + # 调整样式 scale_size_continuous(range = c(0.5, 3)) + theme_minimal() + labs(size = "移民人数", color = "来源国") print(map_with_flow)
3. 交互式地图+桑基图联动
如果需要交互式效果,可以用leaflet做地图,networkD3做桑基图,再通过htmlwidgets组合:
library(leaflet) library(networkD3) library(htmlwidgets) # 准备桑基图数据 sankey_nodes <- data.frame(name = unique(c(clean_flow_data$Origin, clean_flow_data$Destination))) sankey_links <- clean_flow_data %>% mutate( source = match(Origin, sankey_nodes$name) - 1, target = match(Destination, sankey_nodes$name) - 1, value = `Number of Emigrants` ) # 生成桑基图 sankey_plot <- sankeyNetwork( Links = sankey_links, Nodes = sankey_nodes, Source = "source", Target = "target", Value = "value", NodeID = "name", fontSize = 12, nodeWidth = 20 ) # 生成交互式地图 leaflet_map <- leaflet() %>% addTiles() %>% addMarkers(data = flow_with_coords %>% distinct(Origin, lon_origin, lat_origin), lng = ~lon_origin, lat = ~lat_origin, popup = ~Origin) %>% addMarkers(data = flow_with_coords %>% distinct(Destination, lon_dest, lat_dest), lng = ~lon_dest, lat = ~lat_dest, popup = ~Destination) %>% addPolylines(data = flow_with_coords, lng = ~c(lon_origin, lon_dest), lat = ~c(lat_origin, lat_dest), weight = ~`Number of Emigrants`/500, opacity = 0.7, color = "red") # 左右布局组合两个组件 combineWidgets(sankey_plot, leaflet_map, ncol = 2, widths = c(4,6))
二、其他可选方案
- Python:用Plotly绘制交互式桑基图,Folium做地图,再通过Dash框架实现两者联动,适合熟悉Python的场景。
- JavaScript(D3.js):最灵活的方案,可直接同时绘制地图和桑基图层,完全自定义样式与交互逻辑,但需要前端开发基础。
内容的提问来源于stack exchange,提问作者Yui Aoki
相关产品推荐
相关产品推荐

