2016-08-04 21 views
1

Ich habe einen großen 3D-HDF5-Datensatz, der Position (X, Y) und Zeit für eine bestimmte Variable darstellt. Als nächstes habe ich ein 2D-Nummernfeld, das eine Klassifizierung für die gleiche (X, Y) Position enthält. Was ich erreichen möchte, ist, dass ich alle Zeitreihen aus dem 3D-HDF5-Datensatz extrahieren kann, die unter eine bestimmte Klasse im 2D-Array fallen.Indizieren eines großen 3D-HDF5-Datensatzes für eine Teilmenge basierend auf einer 2D-Bedingung

Hier ist mein Beispiel:

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)) 

Jetzt haben wir unsere 3D-Datensatz HDF5 und eine Klassifizierung 2D. Lassen Sie uns für Pixel suchen, die unter Klassennummer fallen ‚3‘

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

Das gibt mir ein Tupel von Größe 2, die die X enthält, Y-Paare, die den Zustand entsprechen, und in meinem willkürliches Beispiel die Menge der Paare ist 544433 Wie soll ich jetzt diese idx Variable verwenden, um ein 2D-Array der Größe (544433,53) zu erstellen, das die 544433-Zeitreihe der Pixel mit der Klassifizierungsklassennummer '3' enthält?

Ich habe einige Tests mit ausgefallener Indizierung und reinen 3D numpy Arrays und diesem Beispiel würde gut funktionieren:

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

jedoch der HDF5-Datensatz zu groß ist, um eine numpy Array zu konvertieren; wenn ich versuche, die gleiche Indexierungsmethode direkt auf dem HDF5-Datensatz zu verwenden:

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

Es wirft mir einen Fehler:

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 

Eine andere Sache, habe ich versucht, np.repeat ist die Klassifizierung Array in den dritten Dimension, um ein 3D-Array zu erstellen, das der Form des HDF5-Datasets entspricht. Die idx Variablen als bekommen ein Tupel von Größe 3:

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

Aber die folgende Anweisung als die exakt gleichen Fehler führt:

NDVI_subset = np.array(NDVI_data[idx]) 

Ist dies, weil der HDF5-Datensatz funktioniert anders im Vergleich zu einem reinen numpy Array ? Die Dokumentation sagt "Auswahlkoordinaten müssen in aufsteigender Reihenfolge gegeben werden"

Hat jemand in diesem Fall einen Vorschlag, wie ich das zum Funktionieren bringen könnte, ohne den vollen HDF5-Datensatz in den Speicher einzulesen (was nicht funktioniert)) Vielen Dank!

+0

Was bedeutet 'h5py' doc sagen über erweiterte oder ausgefallene Indizierung? Ich würde das studieren und dann einen viel kleineren Testfall aufstellen, in dem ich diese Art der Indexierung auf dem 2D-Array testen kann, bevor ich zwei 3D verschiebe. Und wo ich alle Werte drucken kann. Es ist sicherlich möglich, dass H5 in der Indizierung eingeschränkter ist. – hpaulj

+0

http://docs.h5py.org/en/latest/high/dataset.html#fancy-indexing – hpaulj

Antwort

3

Advanced/Phantasie Indizierung in h5py ist nicht annähernd so allgemein wie mit np.ndarray.

einen kleinen Testfall ein:

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) 

Ich kann alle ungeraden Werte auswählen, mit:

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 

Ich kann Index für eine einzelne Dimension mit einer Liste wie: dset[[1,2,3],...], aber sich wiederholende Index Werte oder Ändern der Reihenfolge erzeugt einen Fehler, dset[[1,1,2,2],...] oder dset[[2,1,0],...]. dset[:,[0,1],:] ist in Ordnung.

Mehrere Scheiben sind in Ordnung, dset[0:3,1:3,:] oder eine Scheibe und Liste, dset[0:3,[1,2],:].

Aber 2 Listen dset[[0,1,2],[1,2],:] erzeugt ein

TypeError: Only one indexing vector or array is currently allowed for advanced selection 

So ist der Index Tupel für np.where in mehrfacher Hinsicht falsch ist.

Ich weiß nicht, wie viel davon eine Einschränkung der h5 Speicher ist, und wie viel ist nur unvollständige Entwicklung in der h5py-Modul. Vielleicht ein bisschen von beidem.

Sie müssen also einfachere Chunks aus der Datei laden und die feinere Indizierung der resultierenden numpigen Arrays durchführen.

In meinem odd values Fall, ich muss nur tun:

In [225]: dset[:,:,1] 
Out[225]: 
array([[ 1, 3, 5], 
     [ 7, 9, 11], 
     [13, 15, 17], 
     [19, 21, 23], 
     [25, 27, 29]]) 
+0

Vielen Dank für die Freigabe dieses Beispiels, es verdeutlicht die Einschränkungen der h5py Indizierung. Ich sehe Ihre Lösung für den Fall der "ungeraden Werte", aber ich befürchte, dass es in meinem Fall keine so einfache Lösung gibt. Ich müsste das 2D-Array für jeden Zeitschritt einzeln ausschneiden und dann die ausgefallene Indizierung auf dem Numpy-Array durchführen, aber das scheint keine schnelle und elegante Lösung zu sein. – Kristof