我如何提取存储在HDF5中两个索引之间的多维数组的所有连续值?

问题描述 投票:0回答:1

我有一个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获取两个索引之间的可迭代列表?

python arrays numpy indices
1个回答
0
投票

稍微紧凑:

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]

© www.soinside.com 2019 - 2024. All rights reserved.