如何在R中用ggplot绘制保留原始网格的netCDF数据地图
解决方案:用ggplot绘制NetCDF原始网格(北半球正射投影)
以下是针对需求的完整实现步骤,解决geom_point间距错误和geom_raster失效的问题:
1. 加载依赖包
library(ncdf4) library(ggplot2) library(dplyr) library(tidyr) library(sf)
2. 读取并整理NetCDF数据
先读取数据,提取单时间片的气温、经度、纬度,将宽格式数据转为ggplot所需的长格式,同时修正NOAA数据常见的0-360经度范围为-180到180:
# 读取nc文件 nc <- nc_open("air.1999.nc") # 提取第一个时间片的气温数据 air <- ncvar_get(nc, "air", start = c(1, 1, 1), count = c(-1, -1, 1)) lon <- ncvar_get(nc, "lon") lat <- ncvar_get(nc, "lat") nc_close(nc) # 修正经度范围 lon[lon > 180] <- lon[lon > 180] - 360 # 转为长格式数据框并过滤北半球数据 df <- expand_grid(lon = lon, lat = lat) %>% mutate(air = as.vector(air)) %>% filter(lat >= 0)
3. 用geom_tile绘制精准原始网格(推荐)
geom_tile是绘制固定大小地理网格的最优选择,能完美匹配1×1度的原始分辨率,结合coord_sf实现正射投影:
# 定义北极正射投影CRS(EPSG:3413) ortho_crs <- st_crs("EPSG:3413") ggplot(df, aes(x = lon, y = lat)) + # 绘制1×1度网格,fill绑定气温数据 geom_tile(aes(fill = air), color = NA) + # 需显示网格线可改为color="white" # 设置颜色标尺 scale_fill_viridis_c(name = "Air Temp (°C)") + # 应用正射投影,限制北半球范围 coord_sf(crs = ortho_crs, xlim = c(-180, 180), ylim = c(0, 90)) + # 调整主题 theme_minimal() + labs(x = "", y = "", title = "1999年北半球气温原始网格(1×1°)")
4. 修复geom_raster的使用问题
若坚持使用geom_raster,需关闭插值并确保数据经纬度排序正确:
ggplot(df, aes(x = lon, y = lat)) + geom_raster(aes(fill = air), interpolate = FALSE) + scale_fill_viridis_c(name = "Air Temp (°C)") + coord_sf(crs = ortho_crs, xlim = c(-180, 180), ylim = c(0, 90)) + theme_minimal()
关键说明
- 弃用
geom_point的原因:geom_point的size是相对像素值,无法精准匹配地理坐标上的1×1度网格,必然出现间距或填充不全问题。 - 投影替换:若需其他北半球正射投影,可替换对应EPSG码(如EPSG:4087)。
- 网格线控制:需显示原始网格分隔线,将
geom_tile的color参数设为"white"或其他颜色即可。
内容的提问来源于stack exchange,提问作者Josh Culpepper
相关产品推荐
相关产品推荐

