使用xarray写入数据集为何远慢于读取?
问题原因与解决方案
核心原因
- 编码/压缩设置丢失:原始NetCDF文件大概率启用了压缩(如deflate)、分块等优化,但
xr.open_mfdataset合并后,切片得到的数据集不会自动继承这些编码配置,写入时xarray使用默认参数,导致写入效率大幅下降。 - 合并后的数据结构开销:合并后的数据集将所有时间步的数据整合为一个大数组,即使切片单个时间步,xarray在写入时仍需处理合并后的元数据和数组结构,额外增加了耗时。
- 不必要的合并操作:你的需求是“无任何处理地保存数据集”,合并所有文件再切片写入完全是冗余操作,反而引入了额外开销。
解决方案
方案1:直接复制文件(最快)
如果仅需转移文件路径、无需修改内容,直接用文件系统工具复制,速度远快于xarray读写:
# 命令行方式 cp /path/to/input/*.nc /path/to/output/
或Python实现:
import glob import shutil for file in glob.glob("/path/to/input/*.nc"): output_path = file.replace("/path/to/input", "/path/to/output") shutil.copy(file, output_path)
方案2:循环读取单个文件写入
如果需要对文件做极简单处理(如修改文件名、少量元数据调整),直接循环读取单个文件并写入,速度与单个文件写入一致:
import glob import xarray as xr file_list = glob.glob("/path/to/input/*.nc") for file_path in file_list: ds = xr.open_dataset(file_path) # 可在此添加少量处理逻辑(如修改属性) output_path = file_path.replace("/path/to/input", "/path/to/output") ds.to_netcdf(output_path)
按你的测试数据,单个文件写入耗时~78ms,4000个文件总耗时约5分钟,远低于5小时。
方案3:保留原始编码写入(若必须合并后切片)
如果确实需要合并后再切片写入,需从原始文件提取编码配置,写入时指定:
import xarray as xr # 读取一个原始文件获取编码配置 ds_original = xr.open_dataset("/path/to/input/first_file.nc") encoding = {var: ds_original[var].encoding for var in ds_original.data_vars} # 合并所有文件 ds_all = xr.open_mfdataset("/path/to/input/*.nc") # 切片并写入,指定编码 for i in range(len(ds_all.time)): ds_sel = ds_all.isel(time=i) output_path = f"/path/to/output/file_{i}.nc" ds_sel.to_netcdf(output_path, encoding=encoding)
此方法能恢复原始文件的压缩/分块优化,大幅提升写入速度。
内容的提问来源于stack exchange,提问作者Ress
相关产品推荐
相关产品推荐

