根据2D条件索引大型3D HDF5数据集以进行子集化

时间:2016-08-04 08:11:08

标签: python arrays numpy indexing hdf5

我有一个大的3D HDF5数据集,它代表某个变量的位置(X,Y)和时间。接下来,我有一个2D numpy数组,包含相同(X,Y)位置的分类。我想要实现的是,我可以从3D HDF5数据集中提取所有时间序列,这些数据集属于2D阵列中的某个类。

这是我的榜样:

import numpy as np
import h5py

# Open the HDF5 dataset
NDVI_file = 'NDVI_values.hdf5'
f_NDVI = h5py.File(NDVI_file,'r')
NDVI_data = f_NDVI["NDVI"]

# See what's in the dataset
NDVI_data
<HDF5 dataset "NDVI": shape (1319, 2063, 53), type "<f4">

# Let's make a random 1319 x 2063 classification containing class numbers 0-4
classification = np.random.randint(5, size=(1319, 2063))

现在我们有3D HDF5数据集和2D分类。让我们查找属于班级编号的像素&#39; 3&#39;

# Look for the X,Y locations that have class number '3'
idx = np.where(classification == 3)

这会返回一个大小为2的元组,其中包含与条件匹配的X,Y对,在我的随机示例中,对的数量为544433.我应该如何使用此idx变量创建一个2D数组大小(544433,53),其中包含544433个像素的时间序列,这些像素具有分类类别&#39; 3&#39;?

我使用花哨的索引和纯3D numpy数组进行了一些测试,这个例子可以正常工作:

subset = 3D_numpy_array[idx[0],idx[1],:]

然而,HDF5数据集太大而无法转换为numpy数组;当我试图直接在HDF5数据集上使用相同的索引方法时:

# Try to use fancy indexing directly on HDF5 dataset
NDVI_subset = np.array(NDVI_data[idx[0],idx[1],:])

它给我一个错误:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "h5py\_objects.pyx", line 54, in h5py._objects.with_phil.wrapper     (C:\aroot\work\h5py\_objects.c:2584)
File "h5py\_objects.pyx", line 55, in h5py._objects.with_phil.wrapper (C:\aroot\work\h5py\_objects.c:2543)
File "C:\Users\vtrichtk\AppData\Local\Continuum\Anaconda2\lib\site-packages\h5py\_hl\dataset.py", line 431, in __getitem__
selection = sel.select(self.shape, args, dsid=self.id)
File "C:\Users\vtrichtk\AppData\Local\Continuum\Anaconda2\lib\site-packages\h5py\_hl\selections.py", line 95, in select
sel[args]
File "C:\Users\vtrichtk\AppData\Local\Continuum\Anaconda2\lib\site-packages\h5py\_hl\selections.py", line 429, in __getitem__
raise TypeError("Indexing elements must be in increasing order")
TypeError: Indexing elements must be in increasing order

我尝试的另一件事是np.repeat第三维中的分类数组,以创建一个与HDF5数据集的形状相匹配的3D数组。 idx变量比得到大小为3的元组:

classification_3D = np.repeat(np.reshape(classification,(1319,2063,1)),53,axis=2)
idx = np.where(classification == 3)

但是下面的语句会抛出完全相同的错误:

NDVI_subset = np.array(NDVI_data[idx])

这是因为与纯粹的numpy数组相比,HDF5数据集的工作方式不同吗?文档确实说&#34;选择坐标必须按递增顺序给出&#34;

在这种情况下,是否有人建议我如何才能使其工作而无需将完整的HDF5数据集读入内存(这不起作用)? 非常感谢你!

1 个答案:

答案 0 :(得分:4)

np.ndarray中的高级/花哨索引与import h5py f=h5py.File('test.h5','w') dset=f.create_dataset('data',(5,3,2),dtype='i') dset[...]=np.arange(5*3*2).reshape(5,3,2) x=np.arange(5*3*2).reshape(5,3,2) ind=np.where(x%2) 不一样。

设置一个小测试用例:

In [202]: ind
Out[202]: 
(array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4], dtype=int32),
 array([0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2], dtype=int32),
 array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32))

In [203]: x[ind]
Out[203]: array([ 1,  3,  5,  7,  9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29])
In [204]: dset[ind]
...
TypeError: Indexing elements must be in increasing order

我可以选择所有奇数值:

dset[[1,2,3],...]

我可以使用像dset[[1,1,2,2],...]之类的列表对单个维度建立索引,但重复索引值或更改顺序会产生错误dset[[2,1,0],...]dset[:,[0,1],:]dset[0:3,1:3,:]没问题。

可以使用多个切片,dset[0:3,[1,2],:]或切片和列表dset[[0,1,2],[1,2],:]

但是2个列表TypeError: Only one indexing vector or array is currently allowed for advanced selection 会产生

np.where

因此h5的索引元组在几个方面是错误的。

我不知道这有多少是h5py存储的约束,而odd values模块中只有不完整的开发。也许两者兼而有之。

因此,您需要从文件中加载更简单的块,并对生成的numpy数组执行更高级的索引。

在我的In [225]: dset[:,:,1] Out[225]: array([[ 1, 3, 5], [ 7, 9, 11], [13, 15, 17], [19, 21, 23], [25, 27, 29]]) 案例中,我只需要这样做:

dump