2015-08-17 18 views
7

I eine numpy Array haben, die 4-dimensionale Vektoren enthält, die das folgende Format aufweisen (x, y, z, w)eine numpy Array basierend auf dem größten Wert

Die Größe des Arrays ist 4 x N. Nun, die Daten, die ich habe, ist, wo ich (x, y, z) räumliche Positionen habe und w eine bestimmte Messung an dieser Stelle hält. Nun könnte es mehrere Messungen geben, die mit einer (x, y, z) -Position verbunden sind (gemessen als Floats).

Was ich tun möchte, ist das Array zu filtern, so dass ich ein neues Array bekomme, wo ich die maximale Messung für jede Position (x, y, z) erhalten.

Also, wenn meine Daten wie ist:

x, y, z, w1 
x, y, z, w2 
x, y, z, w3 

wo w1 größer als w2 und w3 ist, wäre die gefilterten Daten:

x, y, z, w1 

mehr so ​​konkret sagen, ich habe Daten wie:

[[ 0.7732126 0.48649481 0.29771819 0.91622924] 
[ 0.7732126 0.48649481 0.29771819 1.91622924] 
[ 0.58294263 0.32025559 0.6925856 0.0524125 ] 
[ 0.58294263 0.32025559 0.6925856 0.05 ] 
[ 0.58294263 0.32025559 0.6925856 1.7 ] 
[ 0.3239913 0.7786444 0.41692853 0.10467392] 
[ 0.12080023 0.74853649 0.15356663 0.4505753 ] 
[ 0.13536096 0.60319054 0.82018125 0.10445047] 
[ 0.1877724 0.96060999 0.39697999 0.59078612]] 

Dies sollte zurückkehren

[[ 0.7732126 0.48649481 0.29771819 1.91622924] 
[ 0.58294263 0.32025559 0.6925856 1.7 ] 
[ 0.3239913 0.7786444 0.41692853 0.10467392] 
[ 0.12080023 0.74853649 0.15356663 0.4505753 ] 
[ 0.13536096 0.60319054 0.82018125 0.10445047] 
[ 0.1877724 0.96060999 0.39697999 0.59078612]] 
+0

werden die Einträge für die gleiche (x, y, z) Position immer aufeinanderfolgend sein, wie es in den Abtastdaten oder werden sie zerstreut werden? Wie viele Einträge haben Sie in der Praxis? – jme

+0

Sie könnten leider verstreut sein. Sie werden nie mehr als 4 sein. Leistung ist zum Glück nicht kritisch. – Luca

+5

FYI: Dies ist eine sogenannte "Group-by" -Operation (vgl. Http://pandas.pydata.org/pandas-docs/stable/groupby.html). Sie gruppieren sich nach den ersten drei Spalten und wenden dann die maximale Funktion auf die Gruppen an. Das ist ziemlich einfach mit einer Bibliothek wie Pandas (http://pandas.pydata.org/). –

Antwort

3

Dies ist gewunden, aber es ist wahrscheinlich so gut wie man nur erhalten mit numpy wollen ...

Erstens verwenden wir lexsort um alle Einträge mit den gleichen Koordinaten zusammen zu setzen. Mit a ist Ihre Probe Array:

>>> perm = np.lexsort(a[:, 3::-1].T) 
>>> a[perm] 
array([[ 0.12080023, 0.74853649, 0.15356663, 0.4505753 ], 
     [ 0.7732126 , 0.48649481, 0.29771819, 0.91622924], 
     [ 0.7732126 , 0.48649481, 0.29771819, 1.91622924], 
     [ 0.1877724 , 0.96060999, 0.39697999, 0.59078612], 
     [ 0.3239913 , 0.7786444 , 0.41692853, 0.10467392], 
     [ 0.58294263, 0.32025559, 0.6925856 , 0.0524125 ], 
     [ 0.58294263, 0.32025559, 0.6925856 , 0.05  ], 
     [ 0.58294263, 0.32025559, 0.6925856 , 1.7  ], 
     [ 0.13536096, 0.60319054, 0.82018125, 0.10445047]]) 

Beachten Sie, dass die Achse durch Umkehr, wir durch x sind Sortieranlagen, Bindungen mit y brechen, dann z, dann w.

Weil es das Maximum suchen wir, wir müssen nur den letzten Eintrag in jeder Gruppe nehmen, die eine ziemlich einfache Sache zu tun:

>>> a_sorted = a[perm] 
>>> last = np.concatenate((np.all(a_sorted[:-1, :3] != a_sorted[1:, :3], axis=1), 
          [True])) 
>>> a_unique_max = a_sorted[last] 
>>> a_unique_max 
array([[ 0.12080023, 0.74853649, 0.15356663, 0.4505753 ], 
     [ 0.13536096, 0.60319054, 0.82018125, 0.10445047], 
     [ 0.1877724 , 0.96060999, 0.39697999, 0.59078612], 
     [ 0.3239913 , 0.7786444 , 0.41692853, 0.10467392], 
     [ 0.58294263, 0.32025559, 0.6925856 , 1.7  ], 
     [ 0.7732126 , 0.48649481, 0.29771819, 1.91622924]]) 

Wenn Sie lieber nicht den Ausgang haben sortiert, sondern sie in der ursprünglichen Reihenfolge halten sie in der ursprünglichen Anordnung kam, können Sie auch mit Hilfe von perm erhalten, dass:

>>> a_unique_max[np.argsort(perm[last])] 
array([[ 0.7732126 , 0.48649481, 0.29771819, 1.91622924], 
     [ 0.58294263, 0.32025559, 0.6925856 , 1.7  ], 
     [ 0.3239913 , 0.7786444 , 0.41692853, 0.10467392], 
     [ 0.12080023, 0.74853649, 0.15356663, 0.4505753 ], 
     [ 0.13536096, 0.60319054, 0.82018125, 0.10445047], 
     [ 0.1877724 , 0.96060999, 0.39697999, 0.59078612]]) 

Dies wird nur für die maximale Arbeit, und es kommt als Neben Produkt der Sortierung. Wenn Sie nach einer anderen Funktion sind, sagen, dass das Produkt aller gleich Koordinaten Einträge, Sie so etwas wie tun könnte:

>>> first = np.concatenate(([True], 
          np.all(a_sorted[:-1, :3] != a_sorted[1:, :3], axis=1))) 
>>> a_unique_prods = np.multiply.reduceat(a_sorted, np.nonzero(first)[0]) 

Und Sie werden ein wenig um mit diesen Ergebnissen spielen müssen, um Ihre Rückkehr Array zu montieren.

-1

Sie können logische Indexierung verwenden.

werde ich Zufallsdaten für ein Beispiel verwenden:

>>> myarr = np.random.random((6, 4)) 
>>> print(myarr) 
[[ 0.7732126 0.48649481 0.29771819 0.91622924] 
[ 0.58294263 0.32025559 0.6925856 0.0524125 ] 
[ 0.3239913 0.7786444 0.41692853 0.10467392] 
[ 0.12080023 0.74853649 0.15356663 0.4505753 ] 
[ 0.13536096 0.60319054 0.82018125 0.10445047] 
[ 0.1877724 0.96060999 0.39697999 0.59078612]] 

Um die Zeile oder Zeilen, wo die letzte Spalte am größten ist, dies zu tun:

>>> greatest = myarr[myarr[:, 3]==myarr[:, 3].max()] 
>>> print(greatest) 
[[ 0.7732126 0.48649481 0.29771819 0.91622924]] 

Was dies tut, ist es bekommt die letzte Spalte von myarr, und findet das Maximum dieser Spalte, findet alle Elemente dieser Spalte gleich dem Maximum und erhält dann die entsprechenden Zeilen.

+0

Dies ist nicht das Verhalten, das ich suche. Ich habe die Frage überarbeitet, um sie hoffentlich klarer zu machen. – Luca

-1

können Sie verwenden np.argmax

x[np.argmax(x[:,3]),:]

>>> x = np.random.random((5,4)) 
>>> x 
array([[ 0.25461146, 0.35671081, 0.54856798, 0.2027313 ], 
     [ 0.17079029, 0.66970362, 0.06533572, 0.31704254], 
     [ 0.4577928 , 0.69022073, 0.57128696, 0.93995176], 
     [ 0.29708841, 0.96324181, 0.78859008, 0.25433235], 
     [ 0.58739451, 0.17961551, 0.67993786, 0.73725493]]) 
>>> x[np.argmax(x[:,3]),:] 
array([ 0.4577928 , 0.69022073, 0.57128696, 0.93995176]) 
+0

Dies ist nicht das Verhalten, das ich suche. Ich habe die Frage überarbeitet, um sie hoffentlich klarer zu machen. – Luca

2

Ich sehe, dass Sie bereits den Hinweis auf Pandas in den Kommentaren bekommen haben. FWIW, hier erfahren Sie, wie Sie das gewünschte Verhalten erzielen können, vorausgesetzt, Sie kümmern sich nicht um die endgültige Sortierreihenfolge, da groupby sie ändert.

In [14]: arr 
Out[14]: 
array([[ 0.7732126 , 0.48649481, 0.29771819, 0.91622924], 
     [ 0.7732126 , 0.48649481, 0.29771819, 1.91622924], 
     [ 0.58294263, 0.32025559, 0.6925856 , 0.0524125 ], 
     [ 0.58294263, 0.32025559, 0.6925856 , 0.05  ], 
     [ 0.58294263, 0.32025559, 0.6925856 , 1.7  ], 
     [ 0.3239913 , 0.7786444 , 0.41692853, 0.10467392], 
     [ 0.12080023, 0.74853649, 0.15356663, 0.4505753 ], 
     [ 0.13536096, 0.60319054, 0.82018125, 0.10445047], 
     [ 0.1877724 , 0.96060999, 0.39697999, 0.59078612]]) 

In [15]: import pandas as pd 

In [16]: pd.DataFrame(arr) 
Out[16]: 
      0   1   2   3 
0 0.773213 0.486495 0.297718 0.916229 
1 0.773213 0.486495 0.297718 1.916229 
2 0.582943 0.320256 0.692586 0.052413 
3 0.582943 0.320256 0.692586 0.050000 
4 0.582943 0.320256 0.692586 1.700000 
5 0.323991 0.778644 0.416929 0.104674 
6 0.120800 0.748536 0.153567 0.450575 
7 0.135361 0.603191 0.820181 0.104450 
8 0.187772 0.960610 0.396980 0.590786 

In [17]: pd.DataFrame(arr).groupby([0,1,2]).max().reset_index() 
Out[17]: 
      0   1   2   3 
0 0.120800 0.748536 0.153567 0.450575 
1 0.135361 0.603191 0.820181 0.104450 
2 0.187772 0.960610 0.396980 0.590786 
3 0.323991 0.778644 0.416929 0.104674 
4 0.582943 0.320256 0.692586 1.700000 
5 0.773213 0.486495 0.297718 1.916229 
+0

Danke. Sehr gute Lösung. Ich werde das auch im Detail erkunden. – Luca

2

Sie können mit lex-sorting Eingangsarray beginnen Einträge zu bringen mit identischen ersten drei Elemente hintereinander. Erstellen Sie dann ein weiteres 2D-Array, um die letzten Spalteneinträge zu speichern, sodass Elemente, die jedem doppelten Triplet entsprechen, in die gleichen Zeilen gehen. Als nächstes finden Sie die max entlang axis=1 für diese 2D-Array und haben somit die endgültige Ausgabe max für jedes solche einzigartige Triplet. Hier ist die Implementierung A als Eingangsarray vorausgesetzt -

# Lex sort A 
sortedA = A[np.lexsort(A[:,:-1].T)] 

# Mask of start of unique first three columns from A 
start_unqA = np.append(True,~np.all(np.diff(sortedA[:,:-1],axis=0)==0,axis=1)) 

# Counts of unique first three columns from A 
counts = np.bincount(start_unqA.cumsum()-1) 
mask = np.arange(counts.max()) < counts[:,None] 

# Group A's last column into rows based on uniqueness from first three columns 
grpA = np.empty(mask.shape) 
grpA.fill(np.nan) 
grpA[mask] = sortedA[:,-1] 

# Concatenate unique first three columns from A and 
# corresponding max values for each such unique triplet 
out = np.column_stack((sortedA[start_unqA,:-1],np.nanmax(grpA,axis=1))) 

Probelauf -

In [75]: A 
Out[75]: 
array([[ 1, 1, 1, 96], 
     [ 1, 2, 2, 48], 
     [ 2, 1, 2, 33], 
     [ 1, 1, 1, 24], 
     [ 1, 1, 1, 94], 
     [ 2, 2, 2, 5], 
     [ 2, 1, 1, 17], 
     [ 2, 2, 2, 62]]) 

In [76]: sortedA 
Out[76]: 
array([[ 1, 1, 1, 96], 
     [ 1, 1, 1, 24], 
     [ 1, 1, 1, 94], 
     [ 2, 1, 1, 17], 
     [ 2, 1, 2, 33], 
     [ 1, 2, 2, 48], 
     [ 2, 2, 2, 5], 
     [ 2, 2, 2, 62]]) 

In [77]: out 
Out[77]: 
array([[ 1., 1., 1., 96.], 
     [ 2., 1., 1., 17.], 
     [ 2., 1., 2., 33.], 
     [ 1., 2., 2., 48.], 
     [ 2., 2., 2., 62.]]) 
Verwandte Themen