如何用R语言terra包正确读取含多维度的netCDF文件?
问题描述
我有一个包含lat、lon、time、effect维度的netCDF文件,文件内包含rn、prec、tair三个变量。用R语言的terra包读取时得到不符合预期的结果:
# 存储netCDF数据的托管URL url = "https://github.com/qquusshh/data_so/raw/main/data.nc" # 将netCDF数据下载到当前目录,命名为"data.nc" download.file(url, "data.nc", mode = "wb") # 读取文件 terra::rast("data.nc") #> class : SpatRaster #> dimensions : 360, 3, 2160 (nrow, ncol, nlyr) #> resolution : 1, 1 (x, y) #> extent : -0.5, 2.5, -180, 180 (xmin, xmax, ymin, ymax) #> coord. ref. : #> sources : data.nc:rn (720 layers) #> data.nc:prec (720 layers) #> data.nc:tair (720 layers) #> varnames : rn #> prec #> tair #> names : rn_ef~9.5_1, rn_ef~8.5_1, rn_ef~7.5_1, rn_ef~6.5_1, rn_ef~5.5_1, rn_ef~4.5_1, ...
期望读取后nrow为lat对应的180、ncol为lon对应的360、nlyr为time对应的3,同时保留effect维度,但实际维度不符。而用Python的xarray库读取结果完全符合预期:
# 导入xarray库 import xarray as xr # 打开数据 xr.open_dataset("data.nc")
输出:
<xarray.Dataset> Dimensions: (lat: 180, lon: 360, time: 3, effect: 4) Coordinates: * lat (lat) float32 89.5 88.5 87.5 86.5 85.5 ... -86.5 -87.5 -88.5 -89.5 * lon (lon) float64 -179.5 -178.5 -177.5 -176.5 ... 177.5 178.5 179.5 * time (time) datetime64[ns] 2019-12-29 2019-12-30 2019-12-31 * effect (effect) object 'inst' 'short' 'long' 'static' Data variables: rn (effect, lat, lon, time) float64 ... prec (effect, lat, lon, time) float64 ... tair (effect, lat, lon, time) float64 ...
请问该如何用terra包正确读取该多维度netCDF文件?
解决方案
terra默认会将非空间维度(此处的effect和time)全部堆叠为图层,可通过以下方法针对性读取:
方法1:指定维度筛选读取
先查看文件元数据确认维度信息,再通过sub参数指定要读取的维度组合,精准获取目标数据:
# 查看netCDF元数据,确认维度名称与取值 nc_meta <- terra::nc_meta("data.nc") print(nc_meta) # 读取单个变量的指定effect维度,保留所有time层 rn_inst <- terra::rast("data.nc", sub = "rn[effect='inst', time]") # 查看结果,此时nrow=180、ncol=360、nlyr=3,符合预期 rn_inst # 若要保留所有effect维度,可循环读取后合并 effect_vals <- nc_meta$dimensions$effect$vals all_rn <- lapply(effect_vals, function(e) { terra::rast("data.nc", sub = paste0("rn[effect='", e, "', time]")) }) all_rn <- terra::rast(all_rn)
方法2:借助stars包转换读取
stars对多维netCDF支持更灵活,可先读取再转换为SpatRaster:
library(stars) library(terra) # 读取多维netCDF数据 nc_stars <- read_stars("data.nc") # 转换为SpatRaster,自动按维度组合生成图层 nc_terra <- as(nc_stars, "SpatRaster") # 按effect筛选图层(示例:保留所有inst相关图层) inst_layers <- grep("inst", names(nc_terra), value = TRUE) nc_terra_inst <- nc_terra[[inst_layers]]
方法3:调整源文件维度顺序(可选)
terra默认将前两个维度识别为空间维度,当前文件变量维度顺序为(effect, lat, lon, time),导致空间维度识别错误。若可修改源文件,将维度顺序调整为(lat, lon, time, effect),terra即可自动正确识别空间维度,其余维度堆叠为图层。
内容的提问来源于stack exchange,提问作者bird
相关产品推荐
相关产品推荐

