非WGS 84投影下geom_vline绘制的网格垂直线无法延伸至图幅边界的技术求助
解决非地理投影下网格线无法延伸至图幅边界的问题
这问题我之前做投影地图时也踩过坑!核心原因是你用的geom_hline()和geom_vline()是基于原始WGS84经纬度坐标系绘制的直线,一旦切换到非地理投影(比如你用的ESRI:102003北美阿尔伯斯圆锥投影),这些直线会被投影变形,而且无法自动适配投影后的图幅范围,自然就没法延伸到边界了。
下面给你两种靠谱的解决方案,都能实现“网格线在图像图层上方且铺满图幅”的需求:
方法一:用st_graticule()生成适配投影的经纬网(灵活可控)
这种方法是手动生成适配目标投影的经纬网,然后用geom_sf()绘制,能完美匹配图幅边界,还能自由调整样式:
library("sf") library("rnaturalearth") library("tidyverse") world <- ne_countries(scale = "medium", returnclass = "sf") usa = filter(world, admin =="United States of America") # 生成指定间隔的经纬网,转换到目标投影 graticule <- st_graticule( x = seq(-180, 0, by = 10), # 经度间隔10度,和你原来的设置一致 y = seq(0, 90, by = 5), # 纬度间隔5度 crs = st_crs(4326) ) %>% st_transform(st_crs("ESRI:102003")) # 转换为阿尔伯斯投影 # 绘图:先画地图(zorder设1),再画经纬网(zorder设2,确保在上方) ggplot() + geom_sf(data = usa, fill = "lightblue", color = "black", alpha = .9, zorder = 1) + geom_sf(data = graticule, color = "blue", linetype = "solid", size = 0.5, zorder = 2) + coord_sf( xlim = c(-119, -74), ylim = c(22, 51), default_crs = sf::st_crs(4326), crs = st_crs("ESRI:102003"), expand = TRUE, lims_method = "box", label_axes = list( bottom = "E", top = "E", left = "N", right = "N" )) + xlab(NULL) + ylab(NULL) + theme_bw()+ theme( panel.grid=element_blank(), # 关闭默认网格 plot.background = element_rect(fill = NA, color = NA), panel.background = element_rect(fill = "grey"), axis.text = element_text(size = 12 ), )
方法二:利用coord_sf的内置网格参数(简洁高效)
如果你不想额外生成经纬网对象,可以直接通过theme修改默认网格的样式和层级,同时指定datum让网格适配WGS84经纬度:
library("sf") library("rnaturalearth") library("tidyverse") world <- ne_countries(scale = "medium", returnclass = "sf") usa = filter(world, admin =="United States of America") ggplot() + # 把地图的zorder设为0,让默认网格(zorder默认1)显示在上方 geom_sf(data = usa, fill = "lightblue", color = "black", alpha = .9, zorder = 0) + coord_sf( xlim = c(-119, -74), ylim = c(22, 51), default_crs = sf::st_crs(4326), crs = st_crs("ESRI:102003"), expand = TRUE, lims_method = "box", label_axes = list( bottom = "E", top = "E", left = "N", right = "N" ), datum = st_crs(4326) # 指定网格基于WGS84经纬度生成 ) + xlab(NULL) + ylab(NULL) + theme_bw()+ theme( # 自定义网格样式和间隔 panel.grid.major.x = element_line( color = "blue", linetype = "solid", size = 0.5, xintercept = seq(-180, 0, by=10) ), panel.grid.major.y = element_line( color = "blue", linetype = "solid", size = 0.5, yintercept = seq(0, 90, by=5) ), panel.grid.minor = element_blank(), # 关闭次要网格 plot.background = element_rect(fill = NA, color = NA), panel.background = element_rect(fill = "grey"), axis.text = element_text(size = 12 ), )
为什么原来的方法不行?
geom_hline()/geom_vline()是在原始数据坐标系(WGS84经纬度)下绘制的直线,当你通过coord_sf转换到阿尔伯斯投影时,这些直线会被投影成曲线(圆锥投影的经线是收敛曲线),而且它们的范围只限于原始经纬度对应的投影区域,无法自动扩展到图幅的边界。而上面两种方法都是基于目标投影生成或转换网格线,所以能完美覆盖整个图幅。
内容的提问来源于stack exchange,提问作者Li Yupeng
相关产品推荐
相关产品推荐

