我对创建一个看起来像这样的地图很感兴趣(可以在https://www.axios.com/2017/12/15/the-flow-of-goods- Between-states-1513304375找到):
具体来说,我想用曲线来描绘地图上区域之间的流动,并用较宽的线表示较大的流动,并使用箭头表示流动的方向。如果可能的话,我还希望从 A 到 B 的线不要位于从 B 到 A 的线的顶部,以便观看者区分两者。最好使用
ggplot2
,尽管我对其他解决方案持开放态度。
我会注意到有相关的问题(例如如何在 R 中的地图上绘制的线条上添加方向箭头?、如何在 R 中创建带有方向箭头的地图图表?、在 R 中绘制电子邮件流使用 R 和 https://flowingdata.com/2011/05/11/how-to-map-connections-with-great-circles/)进行映射,但我想知道是否有一个解决方案可以让我一次合并所有元素。 (我不确定之前的解决方案是否解决了 A 到 B 以及 B 到 A 不重叠的问题。)
是的,可以使用
ggplot2
(tidyverse
) 和 sf
。 curvature
的 geom_curve()
必须不为 0,例如。 0.5,为了创建一个没有重叠箭头的椭圆,A--> B 和 B-->A。
这是一个快速尝试。您可能想要为 Alpha 和线宽创建容器。
library(sf)
library(tidyverse)
# Shapefile of US in a almost random CRS, downloaded from
# https://www2.census.gov/geo/tiger/GENZ2018/shp/cb_2018_us_state_20m.zip
us_shp = st_read( "cb_2018_us_state_20m/cb_2018_us_state_20m.shp") %>%
st_transform("ESRI:102003")
# State center (arrow start and end), from datasets::
state_center = state.center %>% as_tibble() %>% st_as_sf(coords=c("x","y") ,
crs = 4326, remove=FALSE)%>%
st_transform("ESRI:102003") %>%
mutate(state_id = 1:n()) %>%
dplyr::mutate(x = sf::st_coordinates(.)[,1],
y = sf::st_coordinates(.)[,2])
# Creation of a 50*50 dataframe, but we will select some states only at the end
state_exchange = expand.grid(state1= 1:50, state2 = 1:50 ) %>%
mutate( values = rnorm(50*50)) %>%
as_tibble() %>%
filter(state1!=state2) %>%
filter( state1 <4, state2<4)
# Adding start-end
state_exchange_sf = state_exchange %>%
left_join( state_center %>% st_drop_geometry(),
by = c("state1" = "state_id"),
suffix= c("","start") ) %>%
left_join( state_center %>% st_drop_geometry(),
by = c("state2" = "state_id"),
suffix= c("","end"))
ggplot()+geom_sf(data= us_shp)+
geom_sf(data=state_center)+
geom_curve( data =state_exchange_sf %>%
st_as_sf(coords= c("x","y"), crs= "ESRI:102003", remove=FALSE),
aes(x= x, y= y, xend= xend, yend=yend,
alpha= values , linewidth = values),
curvature = -0.5 , arrow= grid::arrow() )