Как заставить geom_sf () указывать на север? - PullRequest
4 голосов
/ 17 апреля 2020

Я пытаюсь создать пакет сопоставления для R и ggplot, который позволил бы пользователям определять свои данные, используя десятичные градусы, но использовал бы соответствующую проекцию в зависимости от того, где находятся данные пользователя. Я решил использовать для этой цели пакет ggspatial , поскольку он автоматически преобразует координаты. Пакет ggspatial, в свою очередь, использует пакет sf , который поддерживается ggplot.

Я использую проекцию Arcti c полярная стереография c для данные исходящие> 60 широты. Проекция декартова с метрами от Северного полюса в качестве координатных единиц. Естественно, когда я пытаюсь построить эту проекцию на стороне Pacifi c от Arcti c, север будет направлен вниз (из-за точки y-координат в направлении Северного полюса).

Как повернуть карты, чтобы они указывали на север, используя coord_sf и ggplot? Если нет разумного способа сделать это, вы могли бы предложить способ обойти эту проблему?

Пример данных:

library(rnaturalearth)
library(sp)
library(raster)
library(sf)
#> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
library(ggplot2)
library(ggspatial)

# Get coastline data a example

dt <- rnaturalearth::ne_coastline()

# Clip and reproject the data to Arctic polar stereographic

clip_boundary <- sp::SpatialPolygons(
  list(sp::Polygons(
    list(sp::Polygon(
      data.frame(lon = c(-180, 180, 180, -180), lat = c(60, 60, 90, 90)))), ID = 1)
  ), proj4string = sp::CRS(sp::proj4string(dt)))

arctic <- raster::crop(dt, clip_boundary)

arctic <- sp::spTransform(arctic, sp::CRS("+init=epsg:3995"))
arctic_sf <- sf::st_as_sf(arctic)

# Define the map limits

limits_dd <- c(-160, 160, 60, 80)
limits_dd_shp <- sp::Polygon(
  matrix(c(limits_dd[1], limits_dd[3], limits_dd[1], limits_dd[4], limits_dd[2], 
           limits_dd[4], limits_dd[2], limits_dd[3], limits_dd[1], limits_dd[3]), 
         ncol = 2, byrow = TRUE))
limits_dd_shp <- sp::SpatialPolygons(
  list(sp::Polygons(list(limits_dd_shp), ID = "clip_boundary")), 
  proj4string= sp::CRS("+init=epsg:4326"))
limits_utm_shp <- sp::spTransform(limits_dd_shp, sp::CRS("+init=epsg:3995"))
limits_utm <- unname(c(limits_utm_shp@bbox[1,], limits_utm_shp@bbox[2,]))

ggplot() + 
  ggspatial::layer_spatial(data = arctic_sf) + 
  ggspatial::layer_spatial(data = limits_utm_shp, color = "red", fill = NA)

Карта показывая пример данных. Красный многоугольник указывает область, которая должна быть нанесена на график.

 # Decimal degree north is "wrong way around" because underlying projection defines so

    ggplot() + 
      ggspatial::layer_spatial(data = arctic_sf) + 
      coord_sf(xlim = limits_utm[1:2], ylim = limits_utm[3:4])

    # A dirty trick trying to invert the y-axis does not help

    ggplot() + 
      ggspatial::layer_spatial(data = arctic_sf) + 
      coord_sf(xlim = limits_utm[1:2], ylim = limits_utm[c(4,3)])
    #> Error in st_normalize.sfc(x, c(x_range[1], y_range[1], x_range[2], y_range[2])): domain must have a positive range

    # Neither does scale_y_reverse

    ggplot() + 
      ggspatial::layer_spatial(data = arctic_sf) + 
      coord_sf(xlim = limits_utm[1:2], ylim = limits_utm[3:4]) + 
      scale_y_reverse()
    #> Error in st_normalize.sfc(x, c(x_range[1], y_range[1], x_range[2], y_range[2])): domain must have a positive range

Единственный способ, которым я достиг этого, - это использовать непосредственно декартовы координаты, но этот подход не позволил бы построить данные сверху, используя десятичные градусы (geom_spatial_point) позже.

ggplot(data = arctic) + 
  geom_path(aes(x = long, y = lat, group = group)) + 
  coord_cartesian(xlim = limits_utm[1:2], ylim = limits_utm[c(4,3)])

Создано в 2020-04-17 с помощью Представить пакет (v0.3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...