如何用Python将多份3D NetCDF合并为带模型维度的4D文件并计算月累计降水
解决CMIP6多模型NetCDF合并为4D数据集并计算月累计降水的问题
问题背景
需要合并9个不同气候模型的3D(time, lat, lon)NetCDF降水数据(变量pr),生成包含model维度的4D数据集,同时解决重采样时的ValueError: index must be monotonic for resampling错误,最终计算月累计降水。
当前代码合并后得到的是3D数据集,未保留模型维度,且时间索引不单调导致重采样失败。
错误原因
- 未保留模型维度:原代码用
xr.combine_nested(netcdfs, concat_dim="time")把所有模型的时间维度直接拼接,导致模型信息丢失,变成单一3D数据集。 - 时间索引不单调:多个模型的时间序列被无序拼接,导致
time维度的索引不是严格递增的,触发重采样的单调索引要求错误。
修改后完整代码
import xarray as xr import os from pathlib import Path variables = ['pr'] scenarios = ['historical', 'ssp245'] # 可选值:['historical', 'ssp126', 'ssp245', 'ssp370', 'ssp585'] models = ['UKESM1-0-LL', 'MRI-ESM2-0', 'MIROC6', 'MIROC-ES2L', 'IPSL-CM6A-LR', 'GFDL-ESM4', 'FGOALS-g3', 'CNRM-ESM2-1', 'CanESM5'] processing_fn = Path("/your/actual/processing/path") # 替换为你的实际数据路径 for variable in variables: # 修正保存路径:移至variable循环内,确保使用当前变量值 save_folder = processing_fn / 'local_climate_assessment' / f'{variable}' / 'output' if not os.path.exists(save_folder): os.makedirs(save_folder) model_datasets = [] # 遍历每个模型,加载并标记模型/情景维度 for scenario in scenarios: for model in models: source = processing_fn / 'local_climate_assessment' / f'{variable}' / f'{scenario}' / f'{model}' netcdf_fn = save_folder / f'{variable}_{scenario}_{model}.nc' if not os.path.exists(netcdf_fn): # 合并单模型年度文件,强制按时间排序 ds_model = xr.open_mfdataset( str(source / '*.nc'), combine='nested', concat_dim="time", use_cftime=True, data_vars='minimal', coords='minimal', compat='override' ).sortby('time') ds_model.to_netcdf(netcdf_fn) print(f"已保存单模型文件:{netcdf_fn}") else: ds_model = xr.open_dataset(netcdf_fn, use_cftime=True).sortby('time') # 新增model和scenario维度,保留模型与情景信息 ds_model = ds_model.expand_dims({'model': [model], 'scenario': [scenario]}) model_datasets.append(ds_model) # 按model维度拼接所有数据集,生成4D结构 combined_ds = xr.concat(model_datasets, dim='model') print("\n合并后的4D数据集信息:") print(combined_ds) # 计算月累计降水,确保时间索引单调 monthly_pr = combined_ds.resample(time='M').sum(dim='time', skipna=True) # 保存月累计结果 monthly_save_path = save_folder / f'{variable}_multi_model_monthly.nc' monthly_pr.to_netcdf(monthly_save_path) print(f"\n月累计降水已保存至:{monthly_save_path}")
关键修改说明
- 新增模型/情景维度:
- 用
expand_dims()为每个单模型数据集添加model和scenario维度,保留元数据信息。 - 使用
xr.concat()按model维度拼接,最终生成维度为(model, scenario, time, lat, lon)的4D数据集。
- 用
- 修复时间索引问题:
- 加载每个模型数据后调用
.sortby('time'),确保时间序列严格递增,满足重采样的单调索引要求。
- 加载每个模型数据后调用
- 路径逻辑修正:
- 将
save_folder的定义移到variable循环内部,避免循环外引用未初始化的变量。
- 将
- 月累计计算优化:
- 加入
skipna=True处理数据中的缺失值,避免累计结果出现无效值。
- 加入
内容的提问来源于stack exchange,提问作者CrossLord
相关产品推荐
相关产品推荐

