我有一个2D数组作为数据集存储在HDF5文件中。假设它的尺寸为(100,100)。给定两个索引,例如x1,y1 =(10,50)和x2,y2 =(30,20),我想获取“(10,50)和(30,20)之间的所有元素”并将其读入一个新的一维数组。一种方法是将完整的数据集读入内存,将其展平,然后使用numpy的ravel_multi_index提取相应的“ flat”索引,如下所示:
import numpy as np
dataset = np.random.rand(100,100)
flat_index_1 = np.ravel_multi_index((10,50), (100,100))
flat_index_2 = np.ravel_multi_index((30,20), (100,100))
data_sliced = dataset.flatten()[flat_index_1:flat_index_2]
但是,如果二维数组的尺寸(此处为(100,100))变得比可以有效存储在内存中的尺寸大,则此方法就不好了。如果数据集为(1e6,1e6),则需要加载大量数据集-取决于x1,y1和x2,y2,最终可能只需要少量连续的元素,因此该方法远非理想。因为您不能展平HDF5数据集(不更改文件或将数组读入内存),所以我想知道最好的方法是什么。是否可以使用np.nditer获取两个索引之间的可迭代列表?
稍微紧凑:
data_sliced = dataset.flat[flat_index_1:flat_index_2]
尽管令人惊讶的是,ravel
的使用速度更快:
data_sliced = dataset.ravel()[flat_index_1:flat_index_2]
也就是说,我认为这不适用于h5py
数据集。
使用数组,您的平面索引可以变成高级索引元组:
In [21]: flat_index_1
Out[21]: 1050
In [22]: flat_index_2
Out[22]: 3020
In [23]: idx = np.unravel_index(np.arange(flat_index_1, flat_index_2), (100,100))
In [26]: idx
Out[26]: (array([10, 10, 10, ..., 30, 30, 30]), array([50, 51, 52, ..., 17, 18, 19]))
In [27]: idx[0].shape
Out[27]: (1970,)
In [28]: data_sliced2 = dataset[idx]
In [29]: np.allclose(data_sliced, data_sliced2)
Out[29]: True
我不确定这是否适用于h5py
。它可能违反了增加订单的要求。加h5py
警告此高级索引可能会变慢。
[另一种选择是加载数据集的简单切片,然后从中进行筛选。即使需要一些索引摆弄,它也可能更快。
例如,仅加载我们需要的行:
In [30]: subset = dataset[10:31, :]
In [31]: subset.shape
Out[31]: (21, 100)
In [32]: subset[idx[0]-10, idx[1]].shape
Out[32]: (1970,)
In [33]: np.allclose(subset[idx[0]-10, idx[1]], data_sliced)
Out[33]: True
或
In [34]: idx1 = np.ravel_multi_index((0,50), subset.shape)
In [35]: idx2 = np.ravel_multi_index((20,20), subset.shape)
In [36]: idx1, idx2
Out[36]: (50, 2020)
In [37]: np.allclose(subset.ravel()[idx1:idx2], data_sliced)
Out[37]: True
也选择列可能没有用:dataset[10:31, 20:51]