Карта R - плохое представление границ суши - PullRequest
2 голосов
/ 22 марта 2019

Я наносил на карту южную часть южного полушария. Моя проблема в Австралии, у которой плохо прорисованы границы.

Мои данные:

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) 

enter image description here

1 Ответ

1 голос
/ 22 марта 2019

TLDR

Вам нужно закрыть полигоны.

Объяснение

Давайте обрежем посторонний код и увеличим масштаб Австралии. (Хотя на самом деле проблема существует и для Африки и Южной Америки; она там не так очевидна ...)

Мы видим, что верхняя строка ведет себя неправильно. Он пересекается с береговой линией дальше на юг, а не придерживается правильного уровня широты:

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()

illustration 1

Теперь слой geom_map, по существу, строит полигоны, а ?geom_polygon сообщает:

Полигоны очень похожи на пути (как нарисовано geom_path()) за исключением что начальная и конечная точки соединены, а внутренняя часть окрашена на fill. Групповая эстетика определяет, какие случаи связаны вместе в многоугольник.

Если мы заменим слой geom_map его эквивалентами geom_polygon / geom_path, ситуация станет намного более очевидной: полигон, соответствующий Австралии, не имеет верхней линии . Вместо этого путь начинается в одном углу и заканчивается в противоположном углу. 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()

illustration 2

Решение

Мы можем вручную закрыть каждый многоугольник, повторяя его первую точку в конце. (Для полигонов, которые уже закрыты, это не имеет никакого дополнительного эффекта.)

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()

illustration 3

Применение этого к исходному сценарию использования:

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) 

result

...