用于分块 NumPy 数组的内置方法

Built in Method for chunking a NumPy array

我在 NetCDF4 文件中有大量数据,我正在尝试编写一个脚本来动态分块这些数据以尽可能多地保存在内存中,对其进行计算并保存结果,然后继续到下一个块。

我正在尝试做的一个例子。假设我有一个这样的数组:

import numpy as np
arr = np.random.randint(0, 10, (100, 15, 51))  # Call these x, y, and z coordinates

而我一次只想读取十个 x 坐标,如下所示:

placeholder = 0
for i in range(10, 101, 10):
    tmp_array = arr[placeholder:i, :, :]
    # Do calculations here and save results to file or database
    placeholder += 10

是否有某种内置方法?在这个简单的示例中,它工作得很好,但随着事情变得越来越复杂,我自己管理所有这些似乎会变得很头疼。我知道 Dask,但在这种情况下它对我没有帮助,因为我没有对数据进行数组操作。如果 Dask 也有处理这个问题的方法,它可能对我有用。

您可以使用 np.split,它接受一个数组和块大小或执行拆分的索引列表。你的情况是 np.split(arr, 10),给你一个包含 10 个形状数组的列表 (10, 15, 51).

请注意,如果轴不能等分,则会引发异常,例如,如果你要求大小为 9 的块。如果你想分成几乎相等的块,而不增加,你可以使用 np.array_split 代替。

对于 hdf5 文件,Dask 文档展示了如何为您想到的那种计算创建分块数组:http://docs.dask.org/en/latest/array-creation.html#numpy-slicing。您的 netCDF4 案例可能会或可能不会以相同的方式工作,但如果不是这样,下面关于 delayed 的部分将起到作用。

制作了 dask-array 后,您将希望对 "do something with each chunk" 操作使用 map_blocks 方法(这期望得到一些输出),循环遍历 .blocks 属性,或使用 .to_delayed() 对每件作品做任意事情。究竟哪种适合您取决于您​​想要实现的目标。

您可以通过实现一个惰性生成器来降低复杂性并提高稳健性,该生成器封装您担心的计算并且只 returns 每一步的块。可能是这样的:

def spliterate(buf, chunk):
    for start in range(0, len(buf), chunk):
        yield buf[start:start + chunk]

使用起来非常简单:

for tmp in spliterate(arr, 10):
    # do calculations on tmp, don't worry about bookkeeping