在 ggplot2 中转换 rworldmap

transform rworldmap in ggplot2

我在 ggplot 中有一张地图(由 geom_polygon、线、点和线段组成)。原件在 WGS 中,所有单位都是度 lat/lon。所有附加数据(线和点)也以度为单位。我想将整个事物重新转换为 equal-area 投影 (Mollweide)。第一步(转换底层 rworldmap 多边形)相当轻松,尽管有一些奇怪的水平线 运行 通过。但是,我不确定如何处理下一步。正如我所说,所有数据都以度为单位,我想以度为单位指定 xlim/ylim、轴标签和(弯曲的)网格线。我是否必须将所有内容都转换为 Mollweide 米,或者是否可以通过某种方式轻松地重塑我的最终地图对象?

这就是我到目前为止所展示的这些奇怪的水平线。

library(rworldmap)
library(rgdal)
library(ggplot2)

moll_crs<-CRS("+proj=moll +R=10567000 +lon_0=0 +x_0=0 +y_0=0 +units=m +towgs84=0,0,0,0,0,0,0 +no_defs")

ggplot() + 
  geom_polygon(data = spTransform(getMap(resolution = 'low'), CRSobj = moll_crs), 
               aes(x = long, 
                   y = lat, 
                   group = group),
               fill = 'gray90', 
               colour = 'gray10', 
               size = 0.3) +
  coord_fixed()

这会产生水平线。

编辑:

根据@hrbmstr 的回答,我将他的 GeoJSON 文件与 coord_map("molleweide"):

一起使用
ggplot() + 
  geom_map(data=world, map=world,
           aes(x=long, y=lat, map_id=id), 
           fill="gray90", color="gray10", size=0.3) +
  coord_map("mollweide",
            xlim = c(-50, 40))

xlim 参数把事情搞砸了,添加了水平线。我以为 coord_***(xlim) 参数只是改变了可视区域,但它似乎影响了地图的绘制方式。有任何想法吗?

你可以让ggplot为你做,你也可以通过使用更好的地图来摆脱线条。我在下面引用的 GeoJSON 文件是从 Natural Earth shapefiles and you can just use the shapefile from there (or the optimized GeoJSON I made from here) 创建的。

为了展示它如何处理额外的点,我为美国和澳大利亚添加了接近质心

library(sp)
library(ggplot2)
library(rgdal)
library(rgeos)

world <- readOGR("ne_50m_admin_0_countries.geojson", "OGRGeoJSON")
outline <- bbox(world)
outline <- data.frame(xmin=outline["x","min"],
                      xmax=outline["x","max"],
                      ymin=outline["y","min"],
                      ymax=outline["y","max"])

world <- fortify(world)

points <- data.frame(lon=c(-98.35, 134.21), lat=c(39.5, -25.36))

gg <- ggplot()
gg <- gg + geom_rect(data=outline, 
                     aes(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax), 
                     color=1, fill="white", size=0.3)
gg <- gg + geom_map(data=world, map=world,
                    aes(x=long, y=lat, map_id=id), 
                    fill="gray90", color="gray10", size=0.3)
gg <- gg + geom_point(data=points, aes(x=lon, y=lat), size=3)
gg <- gg + labs(x=NULL, y=NULL)
gg <- gg + coord_map("mollweide")
gg <- gg + theme_bw()
gg <- gg + theme(panel.grid=element_blank())
gg <- gg + theme(panel.border=element_blank())
gg <- gg + theme(axis.ticks=element_blank())
gg <- gg + theme(axis.text=element_blank())
gg


gg

您可以提前剪辑世界以避免 coord_map:

的问题
world <- readOGR("ne_50m_admin_0_countries.geojson", "OGRGeoJSON")
clipper <- as(extent(-50, 40, -60, 60), "SpatialPolygons")
proj4string(clipper) <- CRS(proj4string(world))

world <- gIntersection(world, clipper, byid=TRUE)
world <- fortify(world)

gg <- ggplot()
gg <- gg + geom_map(data=world, map=world,
                    aes(x=long, y=lat, map_id=id), 
                    fill="gray90", color="gray10", size=0.3)
gg <- gg + labs(x=NULL, y=NULL)
gg <- gg + coord_map("mollweide")
gg

(注意:为了避免混乱,我没有包含上面的所有代码)。您也可以使用相同的边界框代码在裁剪地图周围放置投影边框。

从 rworldmap 地图中排除南极洲是纠正烦人的水平线的一种方法。另外请注意,您只需要从 rworldmap::getMap() 中的默认值 resolution 获得的粗分辨率贴图。

这里是您问题第一部分的解决方案,只需对您的代码进行最少的更改。

moll_crs<-CRS("+proj=moll +ellps=WGS84")
#first get countries excluding Antarctica which can crash spTransform
#for a world plot you only need coarse resolution which is the default for getMap()
sPDF <- getMap()[getMap()$ADMIN!='Antarctica',]

ggplot() + 
  geom_polygon(data = spTransform(sPDF, CRSobj = moll_crs), 
               aes(x = long, 
                   y = lat, 
                   group = group),
               fill = 'gray90', 
               colour = 'gray10', 
               size = 0.3) +
  coord_fixed()