如何用Xarray合并空间不重叠、时间偶重叠的数据立方体?
解决方案:合并空间无重叠、时间部分重叠的分块数据立方体
问题示意图
示意图说明:黑色代表t1,红色代表t2,绿色代表t3,蓝色代表t4;填充矩形对应时间戳下数据立方体有值,仅轮廓代表该空间范围填充NaN。
背景
我拥有两个包含3D变量(维度为t,y,x)的数据立方体(datacube_1、datacube_2),二者空间上无重叠,但它们的并集可构成一个更大的集合(合并后的数据立方体)。时间上二者偶尔存在重叠,我希望合并这些数据集,使得每个时间戳下,若对应数据立方体有值则直接拼接,无值的数据立方体空间范围用NaN填充。
场景设置
- Datacube 1:在t1、t3、t4时刻有值
- Datacube 2:在t1、t2、t3时刻有值
- 合并后的数据立方体:t1时刻完整;t2时刻Datacube 1的空间范围为NaN,Datacube 2完整;t3时刻完整;t4时刻Datacube 2的空间范围为NaN,Datacube 1完整。
核心需求
目标是尽可能使用chunks,并让合并后的数据立方体占用内存最小。不希望时间戳被简单追加,能合并的就合并。需要在merge、combine_by_coords、concat、combine_first中选择最适配的方法。
方法选择分析
各方法对比
concat:仅适合同维度结构的数据集拼接,你的两个数据立方体x维度范围不同,直接使用会报错,排除。merge:默认会将变量作为独立字段合并,不符合你将空间范围拼接成单一变量的需求,当前代码用merge会得到两个独立的DataArray,不是目标中的单一合并立方体,排除。combine_first:需先手动对齐坐标,且循环合并多个数据集时效率极低,每次都要全量对齐,不适配分块场景,排除。combine_by_coords:完全匹配你的需求,它会自动对齐所有坐标(时间、空间),将不同空间范围的数据拼接成统一维度,缺失部分自动填充NaN;同时完美支持Dask分块,保留原分块结构,仅在必要时进行块对齐操作,能保证内存占用最小。
修改后的代码示例
两个数据立方体合并示例
import xarray as xr import numpy as np # 定义维度和坐标 t_coords1 = np.array(['2023-01-01', '2023-01-03', '2023-01-04'], dtype='datetime64') # t1, t3, t4 t_coords2 = np.array(['2023-01-01', '2023-01-02', '2023-01-03'], dtype='datetime64') # t1, t2, t3 y_coords = np.arange(0, 1000) x_coords_1 = np.arange(0, 800) # datacube_1的x维度范围 x_coords_2 = np.arange(0, 120) # datacube_2的x维度范围 # 分块创建数据立方体 datacube_1 = xr.DataArray( np.random.rand(len(t_coords1), len(y_coords), len(x_coords_1)), dims=['t', 'y', 'x'], coords={'t': t_coords1, 'y': y_coords, 'x': x_coords_1}, ).chunk({'t': 2, 'y': 100, 'x': 100}) datacube_2 = xr.DataArray( np.random.rand(len(t_coords2), len(y_coords), len(x_coords_2)), dims=['t', 'y', 'x'], coords={'t': t_coords2, 'y': y_coords, 'x': x_coords_2}, ).chunk({'t': 2, 'y': 100, 'x': 100}) # 使用combine_by_coords合并,自动对齐坐标并填充NaN combined = xr.combine_by_coords([datacube_1, datacube_2])
多个数据立方体合并示例
import xarray as xr from dask.diagnostics import ProgressBar # 收集待合并的数据立方体路径 cubes = ['Datacube_1.nc','Datacube_2.nc','Datacube_3.nc','Datacube_4.nc'] # 批量加载所有分块数据集 dataset_list = [xr.open_dataset(cube, chunks={'t': 500, 'y': 100, 'x': 100}) for cube in cubes] # 一次性合并所有数据集,比循环合并效率更高 combined_ds = xr.combine_by_coords(dataset_list) # 保存合并后的数据集,避免内存过载 write_job = combined_ds.to_netcdf("combined_datacube.nc", mode='w', compute=False) with ProgressBar(): print("正在写入文件") write_job.compute()
关键注意事项
combine_by_coords会自动识别共享维度(t、y),合并不同的x坐标为完整范围,缺失数据自动填充NaN。- 批量加载后一次性合并比循环合并效率更高,可避免多次中间对齐操作。
- 保留分块结构确保合并过程中不会加载全量数据到内存,仅在计算/保存时按需处理块,内存占用最小。
内容的提问来源于stack exchange,提问作者Nihilum
相关产品推荐
相关产品推荐

