2017-12-14 2 views
0

Ich benutze Python 3.6 und numpy.Python/numpy Array-Partitionierung

Von einer hdf5-Datei las ich eine Spalte einer Tabelle, die ein 2D-Array ist.

Jede Zeile des Arrays enthält die IDs der Knoten eines finiten Elements.

Die Tabelle ist so strukturiert, dass es sowohl niedrigere als auch höhere Ordnung Elemente in der gleichen Tabelle (die, aber ich nicht ändern kann ein Freiheitsgrad saugt)

wie dies also das Array (mit Ausnahme sieht etwas hält dass es Millionen von Zeilen potentiell)

[[1,2,3,4,0,0,0,0],   #<- 4 Node quad data packed with zeros 
[3,4,5,6,0,0,0,0],    
[7,8,9,10,11,12,13,14],  #<- 8 node quad in the same table as 4 node quad 
[15,16,17,18,19,20,21,22]] 

ich brauche diese Informationen in zwei getrennte Felder zu trennen - eine für den 4 Knoten ein für 8 Knoten Zeilen durchgeführt.

[[1,2,3,4],   
[3,4,5,6]] 

[[7,8,9,10,11,12,13,14], 
[15,16,17,18,19,20,21,22]] 

Moment über den 2D-Array ich Iterieren, in jeder Zeile den Wert des fünften Wertes überprüft und zwei Index Erstellen von Arrays - einer Zeile der Knoten 4 Reihen und einen der 8 Knoten zu identifizieren.

for element in elements: 
    if element[5] == 0: 
     tet4indices.append(index) 
    else:   
     tet10indices.append(index) 
    index+=1 

Dann benutze ich Index Array Slicing die beiden Arrays

tet4s=elements[tet4indices, 0:5] 
tet10s=elements[tet10indices,0:10] 

Die oben genannten Arbeiten zu bekommen, aber es scheint ein bisschen hässlich.

Wenn jemand eine bessere Lösung hat, würde ich dankbar sein, darüber zu hören .....

Vielen Dank im Voraus,

Doug

+0

sind die 4 & 8 Elementreihen in separaten Gruppen oder gemischt? – hpaulj

+0

Die 4 und 8 Elementreihen können gemischt werden – max375

+0

@ max375 Ich fügte eine allgemeine Antwort hinzu, die Ihren Fall behandelt. – kmario23

Antwort

1

In einer Anordnung ist es einfach Zeilen zu finden wo das fünfte Element 0 oder nicht 0:

In [75]: arr = np.array(alist) 
In [76]: arr 
Out[76]: 
array([[ 1, 2, 3, 4, 0, 0, 0, 0], 
     [ 3, 4, 5, 6, 0, 0, 0, 0], 
     [ 7, 8, 9, 10, 11, 12, 13, 14], 
     [15, 16, 17, 18, 19, 20, 21, 22]]) 
In [77]: arr[:,5] 
Out[77]: array([ 0, 0, 12, 20]) 
In [78]: eights = np.where(arr[:,5])[0] 
In [79]: eights 
Out[79]: array([2, 3], dtype=int32) 
In [80]: arr[eights,:] 
Out[80]: 
array([[ 7, 8, 9, 10, 11, 12, 13, 14], 
     [15, 16, 17, 18, 19, 20, 21, 22]]) 
In [81]: fours = np.where(arr[:,5]==0)[0] 
In [82]: arr[fours,:] 
Out[82]: 
array([[1, 2, 3, 4, 0, 0, 0, 0], 
     [3, 4, 5, 6, 0, 0, 0, 0]]) 

oder mit einem boolean Maske

In [83]: mask = arr[:,5]>0 
In [84]: arr[mask,:] 
Out[84]: 
array([[ 7, 8, 9, 10, 11, 12, 13, 14], 
     [15, 16, 17, 18, 19, 20, 21, 22]]) 
In [85]: arr[~mask,:] 
Out[85]: 
array([[1, 2, 3, 4, 0, 0, 0, 0], 
     [3, 4, 5, 6, 0, 0, 0, 0]]) 

Sie sind in gewissem Sinne glücklich, diese klare 0 Markierung zu haben. Ein bestimmter Finite-Elemente-Code dupliziert Knotennummern, um die Anzahl zu reduzieren, z. [1,2,3,3] für ein 3-Knoten-Element in einem 4-Knoten-System. Aber in diesen Fällen funktioniert der Rest der Mathematik gut, auch wenn Sie 2 Knoten zu einem zusammenführen.

+0

Danke hpaulj für diese Lösungen. Sie scheinen beide die gleiche Geschwindigkeit zu haben und reduzieren die in dieser Funktion verbrachte Zeit von 6,5 Sekunden auf 1 Sekunde für ein Array von 6.500.000 tet10 Elementen !!! – max375

0

Dies funktioniert für mich:

a=np.split(your_numpy_array,[4],1) 
tet4s=np.vstack([a[0][i,:] for i in range(len(a[0])) if np.sum(a[1][i,:])==0]) 
tet10s=np.vstack([np.hstack((a[0][i,:],a[1][i,:])) for i in range(len(a[0])) if np.sum(a[1][i,:])>0]) 
0

Dieser Code generischen genug, um Ihren Anwendungsfall zu behandeln. auch wenn Ihre Zeilen verwechselt werden. Beispiel für beide Fälle sind unten angegeben.

Ein Beispiel, wo die Zeilen in Reihenfolge sind:

In [41]: arr 
Out[41]: 
array([[ 1, 2, 3, 4, 0, 0, 0, 0], 
     [ 3, 4, 5, 6, 0, 0, 0, 0], 
     [ 7, 8, 9, 10, 11, 12, 13, 14], 
     [15, 16, 17, 18, 19, 20, 21, 22]]) 

# extract first half 
In [85]: zero_rows = arr[~np.all(arr, axis=1), :] 

In [86]: zero_rows 
Out[86]: 
array([[1, 2, 3, 4, 0, 0, 0, 0], 
     [3, 4, 5, 6, 0, 0, 0, 0]]) 

# to trim the trailing zeros in all the rows 
In [84]: np.apply_along_axis(np.trim_zeros, 1, zero_rows) 
Out[84]: 
array([[1, 2, 3, 4], 
     [3, 4, 5, 6]]) 



# to extract second half 
In [42]: mask_nzero = np.all(arr, axis=1) 

In [43]: arr[mask_nzero, :] 
Out[43]: 
array([[ 7, 8, 9, 10, 11, 12, 13, 14], 
     [15, 16, 17, 18, 19, 20, 21, 22]]) 

Ein Beispiel, wo die Zeilen gemischt-up, sind:

In [98]: mixed 
Out[98]: 
array([[ 3, 4, 5, 6, 0, 0, 0, 0], 
     [ 7, 8, 9, 10, 11, 12, 13, 14], 
     [15, 16, 17, 18, 19, 20, 21, 22], 
     [ 1, 2, 3, 4, 0, 0, 0, 0]]) 

In [99]: zero_rows = mixed[~np.all(mixed, axis=1), :] 

In [100]: zero_rows 
Out[100]: 
array([[3, 4, 5, 6, 0, 0, 0, 0], 
     [1, 2, 3, 4, 0, 0, 0, 0]]) 

In [101]: np.apply_along_axis(np.trim_zeros, 1, zero_rows) 
Out[101]: 
array([[3, 4, 5, 6], 
     [1, 2, 3, 4]]) 

In [102]: mask_nzero = np.all(mixed, axis=1) 

In [103]: mixed[mask_nzero, :] 
Out[103]: 
array([[ 7, 8, 9, 10, 11, 12, 13, 14], 
     [15, 16, 17, 18, 19, 20, 21, 22]])