Python 在存储为一组netcdf文件的较大数据集上使用dask REDUCT函数的正确方法 让我们考虑一个大数据集,它被记录为一组NETCDF文件,就像下面代码创建的一个: import xarray as xr import numpy as np import dask from scipy.stats import median_absolute_deviation import os n_epochs = 200 n_times = 1500 n_series = 10000 def some_process_generating_sequential_data_epochs(): return np.random.rand(n_series, n_times) os.mkdir("temp") # writes 200 files of 120.1 MB each for no_epoch in range(n_epochs): array = xr.DataArray(some_process_generating_sequential_data_epochs()[:, :, None], dims=("series", "times", "epochs"), coords={"series": range(n_series), "times": range(n_times), "epochs": [no_epoch]}) array.chunk({"series": 1000, "times": 500, "epochs":1})\ .to_netcdf("temp/dummy_file_{}.nc".format(no_epoch))

Python 在存储为一组netcdf文件的较大数据集上使用dask REDUCT函数的正确方法 让我们考虑一个大数据集,它被记录为一组NETCDF文件,就像下面代码创建的一个: import xarray as xr import numpy as np import dask from scipy.stats import median_absolute_deviation import os n_epochs = 200 n_times = 1500 n_series = 10000 def some_process_generating_sequential_data_epochs(): return np.random.rand(n_series, n_times) os.mkdir("temp") # writes 200 files of 120.1 MB each for no_epoch in range(n_epochs): array = xr.DataArray(some_process_generating_sequential_data_epochs()[:, :, None], dims=("series", "times", "epochs"), coords={"series": range(n_series), "times": range(n_times), "epochs": [no_epoch]}) array.chunk({"series": 1000, "times": 500, "epochs":1})\ .to_netcdf("temp/dummy_file_{}.nc".format(no_epoch)),python,bigdata,dask,reduce,Python,Bigdata,Dask,Reduce,现在,如果我们想在epochs维度上应用聚合函数,即在文件中分割数据集的维度,我们可以使用 dataset = xr.open_mfdataset("temp/dummy_file_*.nc", chunks={"series": 1000, "times": 500, "epochs":1}, concat_dim='epochs', combine='by_coords') dataset.reduce(np.std, "epoch

现在,如果我们想在epochs维度上应用聚合函数,即在文件中分割数据集的维度,我们可以使用

dataset = xr.open_mfdataset("temp/dummy_file_*.nc", chunks={"series": 1000, "times": 500, "epochs":1}, 
                            concat_dim='epochs', combine='by_coords')

dataset.reduce(np.std, "epochs", allow_lazy=True)\
       .compute().to_netcdf("temp/std.nc")    
明确提到分块是很重要的,否则dask将加载不适合内存的整个文件

默认情况下,将选择块将整个输入文件一次加载到内存中

这显然适用于numpy平均值、std和中值函数。但是,它不适用于其他函数,例如scipy.stats.median_absolute_disease,它将尝试加载整个数据集并触发MemoryError。我怀疑这和一个小男孩有关。在这张票里,他们报告

当你有一个大的数组与均值交互时,问题就出现了, 例如:

x-x.mean.sum.compute

当前的解决方法是事先明确计算平均值

x-x.mean.compute.sum.compute

我试图通过修改scipy.stats版本的中位数绝对偏差来应用这种策略,但没有成功。他们还建议使用dask.set_options split_every=2,现在不推荐使用dask.config.setsplit_every=2,但在这里似乎没有帮助


对这种数据集执行这些reduce操作时,是否有一个适当的、没有从头开始的、或多或少总是有效的习惯用法?

您的问题很长,所以我没有全部阅读。我很抱歉,我试图回答这些问题,但有很多问题

我想你是在问

如何将任意缩减函数应用于大型数据集

答案是你不能。像da.mean这样的操作是用并行算法重写的。您不能只采用Numpy或Scipy版本并按原样应用它。但是,如果您可以考虑一下如何将reduce操作分解为并行操作,那么您可能需要尝试da.reduce函数

或者,如果只沿一个轴应用缩减,则可以重新调整数据,使该轴为单块,然后使用类似map_块的东西以令人尴尬的并行方式应用函数