我正在尝试为 R 和 ggplot 制作一个映射包,允许用户使用十进制度定义他们的数据,但会根据用户数据的位置使用适当的投影。我决定为此目的使用ggspatial包,因为它会自动转换坐标。ggspatial 包反过来使用sf包,它由 ggplot 支持。
我将北极极地立体投影用于源自 >60 纬度的数据。投影是笛卡尔投影,以距离北极的米为坐标单位。自然,当我尝试在北极的太平洋一侧绘制此投影时,北方将指向下方(因为 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)])
由reprex 包于 2020-04-17 创建(v0.3.0)