如何使用xarray处理大规模NetCDF气象数据绘制概率分布图?
优化方案
你原代码中调用.values会将全部分块数据一次性加载到内存,16年数据总规模约为16365501*572=16.7亿个元素,单精度存储就超过6GB,双精度更是超过13GB,远超普通笔记本内存上限,所以会触发内核重启。优化逻辑核心是避免全量数据加载到内存,基于xarray的分块计算能力完成统计:
- 合理配置分块参数:不要使用通用的
chunks=100,按维度设置分块,保证单个分块大小在100MB~200MB区间,降低IO和内存开销 - 分块计算直方图:直接对延迟加载的数组做直方图统计,仅将最终的分箱计数结果加载到内存,内存占用可忽略
- 用统计结果绘图:无需传入全量数组给seaborn,直接用分箱统计结果绘图即可
优化后代码
import matplotlib.pyplot as plt import xarray as xr import numpy as np import seaborn as sns # 1. 按维度设置合理分块,维度名可根据你的实际NC文件维度调整 fname = '20*.nc' ds = xr.open_mfdataset( fname, parallel=True, # 按时间、纬度、经度分块,可根据你设备配置调整大小 chunks={'time': 30, 'lat': 100, 'lon': 100} ) prec = ds.irwin_cdr # 2. 先计算全局值范围,保证分块计算时分箱边界一致 min_val = prec.min().compute() max_val = prec.max().compute() bins = np.linspace(min_val, max_val, 51) # 50个分箱对应51个边界点 # 3. 分块并行计算直方图,仅最终统计结果加载到内存 hist, bin_edges = xr.apply_ufunc( np.histogram, prec, input_core_dims=[[]], output_core_dims=[['bin'], ['bin_edge']], vectorize=True, kwargs={'bins': bins, 'density': True}, # density=True输出概率密度 dask='parallelized', output_dtypes=[np.float64, np.float64] ).compute() # 4. 用统计结果绘图 bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2 sns.barplot(x=bin_centers, y=hist, color="g", width=(bins[1]-bins[0])*0.8) plt.xlabel('irwin_cdr') plt.ylabel('Probability density') plt.show()
可选轻量方案
如果不需要极高精度的概率分布,可随机抽样部分数据绘制,效率更高:
# 随机抽取0.5%的样本,内存占用直接降低200倍,分布误差可忽略 sample_rate = 0.005 prec_sample = prec.where( xr.DataArray(np.random.random(prec.shape) < sample_rate, dims=prec.dims), drop=True ).compute().values.flatten() sns.displot(prec_sample, bins=50, color="g") plt.show()
内容的提问来源于stack exchange,提问作者Krishnaap
相关产品推荐
相关产品推荐

