使用ggplot2的geom_sf绘制Robinson投影地图时数据不显示问题
Robinson投影地图与栅格数据匹配问题解决
核心问题根源
更新RStudio后报错是因为fortify(getMap())的方式已被ggplot2弃用;改用geom_sf后数据不显示,是因为世界地图已转成Robinson投影(米为单位的投影坐标系),但geom_tile用的是经纬度(度为单位的地理坐标系),两者坐标系不匹配,导致数据无法在投影空间渲染。
分步解决代码
1. 正确创建并转换世界地图的sf对象
替换原有的世界地图获取代码,直接用sf标准方式处理:
library(maps) library(sf) library(ggplot2) # 获取世界地图并转为sf对象 world <- sf::st_as_sf(maps::map("world", plot = FALSE, fill = TRUE)) # 定义Robinson投影参数 robinson_crs <- "+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs" # 转换地图到Robinson投影 world_robin <- sf::st_transform(world, robinson_crs)
2. 将你的PM2.5数据转为匹配的坐标系
把经纬度数据框转成sf对象,再同步到Robinson投影:
# 将数据框转为sf对象(默认经纬度是WGS84坐标系) length_sf <- sf::st_as_sf(length_110_2050_MAM, coords = c("X1", "X2"), crs = 4326) # 转换到Robinson投影 length_sf_robin <- sf::st_transform(length_sf, robinson_crs)
3. 两种绘制方案任选
方案一:用sf点模拟tile效果(适合离散数据点)
lengthmap_110_2050_MAM <- ggplot() + geom_sf(data = world_robin) + geom_sf(data = length_sf_robin, aes(fill = X4), shape = 22, size = 3, alpha = 0.8) + # 方形点替代tile scale_fill_gradient(low = "yellow", high = "Red") + labs(title = "Days with PM2.5 > 110 in Mar-Apr-May", x = "Longitude", y = "Latitude") + theme_minimal() + theme(legend.key.width = unit(0.1, 'in'), legend.key.height = unit(0.7, 'in'), legend.position = 'right', plot.title = element_text(size = 10))
方案二:用geom_raster渲染栅格(适合规则网格数据)
如果你的数据是规则栅格,先把经纬度转成Robinson坐标再用栅格绘制:
# 转换经纬度到Robinson坐标并合并原数据 length_110_2050_MAM_robin <- sf::st_as_sf(length_110_2050_MAM, coords = c("X1", "X2"), crs = 4326) %>% sf::st_transform(robinson_crs) %>% sf::st_coordinates() %>% cbind(length_110_2050_MAM) %>% rename(x = X, y = Y) # 绘制地图 lengthmap_110_2050_MAM <- ggplot() + geom_sf(data = world_robin) + geom_raster(data = length_110_2050_MAM_robin, aes(x = x, y = y, fill = X4), alpha = 0.8) + scale_fill_gradient(low = "yellow", high = "Red") + labs(title = "Days with PM2.5 > 110 in Mar-Apr-May", x = "Longitude", y = "Latitude") + coord_sf(crs = robinson_crs) + # 强制坐标系一致 theme_minimal() + theme(legend.key.width = unit(0.1, 'in'), legend.key.height = unit(0.7, 'in'), legend.position = 'right', plot.title = element_text(size = 10))
内容的提问来源于stack exchange,提问作者Y Hur
相关产品推荐
相关产品推荐

