使用 geom_sf 跨越日期变更线时地图上的闭合边界

ber*_*roe 4 maps r coordinate-systems ggplot2 geom-sf

我正在尝试制作一个罗宾逊投影图,该地图以经度 0 为中心,并且穿过 180\xc2\xb0 线的两侧。

\n

我的代码如下:

\n
library("rnaturalearthdata")\nworld <- ne_countries(scale = "medium", returnclass = "sf")\nrobinson = "+proj=robin +lon_0=-90 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"\ntransformed = st_transform(world, robinson)\nggplot(data=transformed) + geom_sf(fill = "gray", colour = "black")+theme_bw()\n
Run Code Online (Sandbox Code Playgroud)\n

这会生成此地图,该地图的方向正确,但所有分割边界都是“由内而外”并环绕整个地图。

\n

在此输入图像描述

\n

9 年前就有这个相关问题,但我希望通过最近的软件包更新,有一个不太复杂的解决方案,这将使我们能够使用而不geom_point()需要额外的转换来绘制纬度/经度数据点。

\n

编辑#2:L. Tyrone 的解决方案对我来说非常有用。要使用此方法绘制点,您必须将它们从数据框转换为具有相同坐标参考系统的 sf 对象,否则纬度/经度将被解释为米,并且最终与 0,0 无法区分:

\n
# Transform with fake data...\nfakedata=data.frame(lat=c(-10,-20,80),lon=c(45,-100,120),tag=c("indian","tropical","arctic"))\ntranspoint = st_as_sf(fakedata,coords=c("lon","lat"),crs=4326)\ndtran = st_transform(transpoint,robinson)\n
Run Code Online (Sandbox Code Playgroud)\n

然后,您可以通过将特殊geometry=stat=声明添加到geom_point或 来绘制它们geom_text_repel

\n
geom_point(data=dtran,aes(geometry=geometry,color=tag),stat="sf_coordinates") +\ngeom_text_repel(data=dtran,aes(geometry=geometry,label=tag),stat="sf_coordinates")\n
Run Code Online (Sandbox Code Playgroud)\n

最终结果:\n成功将虚假数据绘制到地图上

\n

Ler*_*one 7

在投影之前,您需要“破坏”任何交叉 180 度的多边形。st_break_antimeridian()包中的函数是sf实现此目的的最简单方法。它会发出警告,您可以安全地忽略该警告。

library(rnaturalearth)
library(sf)
library(dplyr)
library(ggplot2)

world <- ne_countries(scale = "medium", returnclass = "sf") %>%
  st_set_crs(4326)

robinson <- "+proj=robin +lon_0=-90 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"

world_robinson_90w <- world %>%
  st_break_antimeridian(lon_0 = -90) %>%
  st_transform(crs = robinson)

ggplot() +
  geom_sf(data = world_robinson_90w)
Run Code Online (Sandbox Code Playgroud)

结果

  • 这是一个奇迹。太感谢了。你不知道我为此挣扎了多久。我必须更新我的“sf”才能获得中断反子午线功能,但它正在工作,我什至可以绘制转换点。 (2认同)