R 地图 - 陆地边界的代表性差

R map - poor representation of land borders

我绘制了南半球南部的地图。我的问题是澳大利亚的边界画得不好。

我的数据:

library("maptools")
library("ggplot2")
library("tidyverse")

ylim_map <- c(-90, -30)
xlim_map <- c(-180, 180)
world <- maps::map("world", fill=TRUE, plot=FALSE, ylim = ylim_map)

将数据转换为正确的 ggplot 格式:

IDs <- sapply(strsplit(world$names, ":"), function(x) x[1])
world <- map2SpatialPolygons(world, IDs = IDs, 
                             proj4string = CRS("+proj=longlat +datum=WGS84"))
world_map <- fortify(world)
world_map <- world_map[which(between(world_map$lat, ylim_map[1], ylim_map[2]) &
                               between(world_map$lon, xlim_map[1], xlim_map[2])),]

还有我的情节:

ggplot() +

  coord_map("orthographic", orientation = c(-90, 0, 0), 
            xlim = xlim_map, ylim = c(ylim_map[1], ylim_map[2] + 10)) +

  geom_map(data = world_map, map = world_map,
           aes(x = long, y = lat, map_id = id), fill = "black") +

  geom_text(aes(x = 180, y = ylim_map[2]+5, label = "180°E"), color = "black") +
  geom_text(aes(x = 90, y = ylim_map[2]+5, label = "90°E"), angle = -90, color = "black") +
  geom_text(aes(x = 0, y = ylim_map[2]+5, label = "0°"), color = "black") +
  geom_text(aes(x = -90, y = ylim_map[2]+5, label = "90°W"), angle = 90, color = "black") +

  labs(y = "", x = "") +

  # Theme
  theme(text = element_text(size = 20),
        panel.background = element_blank(),
        axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        axis.line = element_blank(),
        aspect.ratio = 1) 

TLDR:

您需要关闭多边形。

解释:

让我们 trim 去掉多余的代码并放大到澳大利亚。 (虽然实际上非洲和南美洲也存在这个问题;只是那里没有那么明显...)

我们可以看到顶行行为不正常。它与更南的海岸线相交,而不是坚持正确的纬度水平:

ggplot() +
  coord_map("orthographic", orientation = c(-40, 130, 0)) +
  geom_map(data = world_map, map = world_map,
           aes(x = long, y = lat, map_id=id), 
           fill = "darkgrey") +
  theme_bw()

现在 geom_map 图层本质上是在绘制多边形,并且 ?geom_polygon 声明:

Polygons are very similar to paths (as drawn by geom_path()) except that the start and end points are connected and the inside is coloured by fill. The group aesthetic determines which cases are connected together into a polygon.

如果我们用 geom_polygon / geom_path 等价物替换 geom_map 层,情况会变得更加明显: 对应于澳大利亚的多边形没有顶部行。相反,路径从一个角开始,在对角结束。 geom_polygon 用一条直线连接它们,当坐标系不是线性时(coord_map 不是),该直线可能与其他线相交:

ggplot() +
  coord_map("orthographic", 
            orientation = c(-40, 130, 0)) +
  geom_polygon(data = world_map,
               aes(x = long, y = lat, group = group), 
               fill = "lightgrey") +
  geom_path(data = world_map,
            aes(x = long, y = lat, group = group)) +
  theme_bw()

解决方法:

我们可以通过在最后重复第一个点来手动关闭每个多边形。 (对于已经闭合的多边形,这没有额外的效果。)

library(dplyr)

world_map2 <- world_map %>%
  group_by(group) %>%              # each group corresponds to a unique polygon
  arrange(order) %>%               # sort points in the appropriate sequence
  slice(c(1:n(), 1)) %>%           # repeat first row after last row
  mutate(order = seq(1, n())) %>%  # define new order for n+1 rows
  ungroup()

检查多边形现在是否闭合,澳大利亚的顶线现在很好地描绘了它的纬度水平:

ggplot() +
  coord_map("orthographic", 
            orientation = c(-40, 130, 0)) +
  geom_polygon(data = world_map2,
               aes(x = long, y = lat, group = group), 
               fill = "lightgrey") +
  geom_path(data = world_map2,
            aes(x = long, y = lat, group = group)) +
  theme_bw()

将此应用于原始用例:

ggplot() +

  coord_map("orthographic", orientation = c(-90, 0, 0), 
            xlim = xlim_map, ylim = c(ylim_map[1], ylim_map[2] + 10)) +

  geom_map(data = world_map2, map = world_map2,
           aes(x = long, y = lat, map_id = id), fill = "black") +

  geom_text(aes(x = 180, y = ylim_map[2]+5, label = "180°E"), color = "black") +
  geom_text(aes(x = 90, y = ylim_map[2]+5, label = "90°E"), angle = -90, color = "black") +
  geom_text(aes(x = 0, y = ylim_map[2]+5, label = "0°"), color = "black") +
  geom_text(aes(x = -90, y = ylim_map[2]+5, label = "90°W"), angle = 90, color = "black") +

  labs(y = "", x = "") +

  # Theme
  theme(text = element_text(size = 20),
        panel.background = element_blank(),
        axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        axis.line = element_blank(),
        aspect.ratio = 1)