将ggplot2地图旋转到任意角度
类似于ggplot2:如何以特定角度旋转图形?,但我不希望图像/正方形旋转,我希望在框架内旋转数据。
例如,如果我从这个开始:
library(ggplot2)
usa <- maps::map('usa', plot=FALSE)
ggplot(as.data.frame(usa[c("x","y")]), aes(x,y)) +
coord_quickmap() +
geom_path()
我希望能够生成这个:
- 旋转需要保留空间数据的纵横比
- 我需要支持任意旋转,不受 90 度跳跃的限制
- 我想是否可以保留实际的网格(以保留其中的默认行为
ggplot2),但如果不能,我可以手动生成它们 - 我希望通用图的封闭矩形保持不变,包括(此处未显示)标题和副标题
- 如果坐标系不变,我会喜欢它,这意味着我可以添加其他图层,这些图层随后会自动欣赏旋转。@qdread 的回答给出了替代方案,其中单个函数可以计算旋转(尽管我不知道如何使用空间数据在数学上做到这一点)
- 请忽略:
- 左上角的网格问题,我的photoshopping不完整
- x 轴标签,数字错误(y 轴很好)(可以删除,不需要)
我想知道这是否可以通过CRS/projections来完成,但我对它们不够聪明,无法正式/正确地使用它。
回答
edit2:
使用斜墨卡托投影旋转地图:
#crs with 45degree shift using +gamma
# lat_0 and lonc approximate centroid of US
crs_string = +proj=omerc +lat_0=36.934 +lonc=-90.849 +alpha=0 +k_0=.7 +datum=WGS84 +units=m +no_defs +gamma=45"
# states data & libraries in code chunk below
ggplot(states) +
geom_sf() +
geom_sf(data = x, color = 'red') +
coord_sf(crs = crs_string,
xlim = c(-3172628,2201692), #wide limits chosen for animation
ylim = c(-1951676,2601638)) + # set as needed
theme_bw() +
theme(axis.text = element_blank())
伽马动画从 0:360 开始,以 10 度为增量,alpha 常数为 0。伪影来自 gif 压缩,实际图看起来像上面标记为 45 的图。
较早的答案:我认为您可以通过将投影更改为 Lambert 方位角相等面积并+lon_0=x在投影字符串中进行调整,通过从不同的角度“看”地球来“旋转”绘图(包括经纬网)。
这应该可以满足您的大部分目标,但我不知道如何获得精确的度数旋转。
下面我states_sf在绘图之前手动转换了sf 对象。通过对数据使用 crs 4326 并添加+ coord_sf(crs = "+proj=laea +x_0=0 +y_0=0 +lon_0=-140 +lat_0=40")到ggplot() +调用的末尾,可能更容易转换绘图(以及所有正在绘制的 sf 数据)。
#crs with 45degree shift using +gamma
# lat_0 and lonc approximate centroid of US
crs_string = +proj=omerc +lat_0=36.934 +lonc=-90.849 +alpha=0 +k_0=.7 +datum=WGS84 +units=m +no_defs +gamma=45"
# states data & libraries in code chunk below
ggplot(states) +
geom_sf() +
geom_sf(data = x, color = 'red') +
coord_sf(crs = crs_string,
xlim = c(-3172628,2201692), #wide limits chosen for animation
ylim = c(-1951676,2601638)) + # set as needed
theme_bw() +
theme(axis.text = element_blank())
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
library(urbnmapr)
library(tidyverse)
# get sf of the us, remove AK & HI,
# transform to crs 4326 (lat & lon)
states_sf <- get_urbn_map("states", sf = TRUE) %>%
filter(!state_abbv %in% c('AK', 'HI')) %>%
st_transform(4326)
#centroid of us to 'look' at the US from directly above the center
us_centroid <- st_union(states_sf) %>% st_centroid() %>% st_transform(4326)
st_coordinates(us_centroid)
#> X Y
#> 1 -99.38208 39.39364
# Plots, changing the +lon_0=xxx of the projection
p1 <- states_sf %>%
st_transform("+proj=laea +x_0=0 +y_0=0 +lon_0=-99.382 +lat_0=39.394") %>%
ggplot(aes()) +
geom_sf(fill = "black", color = "#ffffff") +
ggtitle('US from above its centroid 39.3N 99.4W')
p2 <- states_sf %>%
st_transform("+proj=laea +x_0=0 +y_0=0 +lon_0=-70 +lat_0=40") %>%
ggplot(aes()) +
geom_sf(fill = "black", color = "#ffffff") +
ggtitle('US from 40N 70W')
p3 <- states_sf %>%
st_transform("+proj=laea +x_0=0 +y_0=0 +lon_0=-50 +lat_0=40") %>%
ggplot(aes()) +
geom_sf(fill = "black", color = "#ffffff") +
ggtitle('US from 40N 50W')
p4 <- states_sf %>%
st_transform("+proj=laea +x_0=0 +y_0=0 +lon_0=-30 +lat_0=40") %>%
ggplot(aes()) +
geom_sf(fill = "black", color = "#ffffff") +
ggtitle('US from 40N 30W')
p5 <- states_sf %>%
st_transform("+proj=laea +x_0=0 +y_0=0 +lon_0=-10 +lat_0=40") %>%
ggplot(aes()) +
geom_sf(fill = "black", color = "#ffffff") +
ggtitle('US from 40N 10W')
p6 <- states_sf %>%
st_transform("+proj=laea +x_0=0 +y_0=0 +lon_0=-140 +lat_0=40") %>%
ggplot(aes()) +
geom_sf(fill = "black", color = "#ffffff") +
ggtitle('US from 40N 140W')
p1
p3
p5
由reprex 包(v0.3.0)于 2021 年 3 月 31 日创建
编辑:
使用投影时,您似乎可以通过 alpha 和 gamma 的组合获得任何角度"+proj=omerc +lonc=-90 +lat_0=40 +gamma=0 +alpha=0"。我不知道它们到底是如何关联的(与方位角有关),但这应该有助于将其可视化:
# Basic template for rotating, keeping US map centered.
# adjust alpha and gamma by trial & error
crs <- "+proj=omerc +lonc=90 +lat_0=40 +gamma=90 +alpha=0"
states_sf %>%
ggplot() +
geom_sf(fill = 'green') +
coord_sf(crs = crs)
可以在此处找到更广泛的 alpha 和 gamma 动画。