2016-07-12 16 views
2

Angenommen, ich habe ein Array (M, N), wo die Werte in jeder "Spalte", N, Datenaufzeichnungen von N verschiedenen Maschinen darstellen. Stellen wir uns vor, jede "Zeile", M, stellt einen eindeutigen "Zeitstempel" dar, in dem Daten für alle N Maschinen aufgezeichnet wurden.Numpy Arrays: Extrahieren bevorzugt geordnete Werte aus Array mit Nans ohne Padding?

Das Array (M, N) ist so strukturiert, dass es bei M = 0 dem allerersten "Zeitstempel" (t0) entspricht und die Zeile M = M (tm) am meisten repräsentiert kürzliche "Zeitstempel" -Aufnahme.

Nennen wir dieses Array "AX". AX [0] würde die aufgezeichneten Daten für N Maschinen zum allerersten "Zeitstempel" liefern. AX [-1] wären die neuesten Aufnahmen.

Hier ist meine Array:

>>AX = np.random.randn(3, 5) 

array([[ 0.53826804, -0.9450442 , -0.10279278, 0.47251871, 0.32050493], 
     [-0.97573464, -0.42359652, -0.00223274, 0.7364234 , 0.83810714], 
     [-0.07626913, 0.85246932, -0.13736392, -1.39977431, -1.39882156]]) 

Nun stell dir vor etwas schief gelaufen ist und die Daten wurden nicht konsequent für jede Maschine bei jedem „Zeitstempel“ erfasst. Um ein Beispiel für zu erstellen, wie die Ausgabe aussehen könnte folgte ich dem Beispiel unter unten stehendem Link einzufügen Nans in zufälligen Positionen im Array:

Create sample numpy array with randomly placed NaNs

>>AX.ravel()[np.random.choice(AX.size, 9, replace=False)] = np.nan 


array([[ 0.53826804, -0.9450442 ,   nan, 0.47251871,   nan], 
     [  nan,   nan,   nan, 0.7364234 , 0.83810714], 
     [-0.07626913,   nan,   nan,   nan,   nan]]) 

Nehmen wir an, dass ich die letzten Werte zur Verfügung stellen müssen der aufgezeichneten Daten. Idealerweise wäre dies so einfach wie der Bezug auf AX [-1]. In diesem speziellen Fall hätte ich kaum Daten, da alles kaputt war.

>>AX[-1] 

array([-0.07626913,   nan,   nan,   nan,   nan]) 

GOAL:

Ich weiß, alle Daten, ist besser als nichts, so würde ich die jüngsten Wert für jede Maschine aufgezeichnet verwenden möchten. In diesem speziellen Szenario, das gut ich konnte ist ein Array mit den Werten liefern:

[-0.07626913, -0.9450442, 0.7364234, 0.83810714] 

Hinweis Spalte 2 der AX keine verwertbaren Daten hatte, so dass ich einfach übersprungen ouput es ist.

Ich finde np.arrays nicht sehr intuitiv und wie ich durch die Dokumentation lese, bin ich überwältigt von der Menge an spezialisierten Funktionen und Transformationen.

Meine ursprüngliche Idee war vielleicht, alle Nans zu einem neuen Array (AY) herauszufiltern und dann die letzte Zeile AY [-1] zu nehmen (vorausgesetzt, dies würde seine wichtige reihenbasierte Reihenfolge beibehalten) dies würde ein Array mit einer seltsamen Form von (ich bin nur ganzzahlige Werte mit der Einfachheit halber hier statt AX Werte) werden zu machen:

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

unter der Annahme, dass sogar möglich ist, zu schaffen, die letzte „Reihe“ nehmen (?) würde [6,5,3] ergeben und würde alles völlig durcheinander bringen. Das Auffüllen eines Arrays mit Werten ist ebenfalls schlecht, da die letzten Werte Pads für 4 von 5 Datenpunkten in der letzten "Zeitstempel" -Zeile wären.

Gibt es einen Weg, um das, was ich will, auf ziemlich schmerzlose Weise zu erreichen, während ich immer noch die np.array-Struktur nutze und Datenframes und Panels vermeide?

Danke!

Antwort

3

Dies ist die Art von Frage, die viele interessante Antworten generieren kann.Jemand wird wahrscheinlich mit einem besseren Weg, als diese kommt, aber die Dinge zu erhalten begonnen, hier ist eine Möglichkeit:

In [99]: AX 
Out[99]: 
array([[ 0.53826804, -0.9450442 ,   nan, 0.47251871,   nan], 
     [  nan,   nan,   nan, 0.7364234 , 0.83810714], 
     [-0.07626913,   nan,   nan,   nan,   nan]]) 

np.isfinite(AX) ist ein boolean-Array, das Wahre ist, wo AX ist nicht nan (und nicht unendlich, aber ich nehme an dieser Fall ist nicht relevant). Für ein boolesches Array B gibt B.argmax(axis=0) die Indizes zuerst True Wert in jeder Spalte. Um die Indizes des letzten True-Werts zu erhalten, kehren Sie das Array um, nehmen Sie das Argument argmax und subtrahieren Sie dann das Ergebnis von der Anzahl der Zeilen minus 1; das heißt B.shape[0]-1 - B[::-1].argmax(axis=0). In diesem Fall B ist np.isfinite(AX), so haben wir:

In [100]: k = AX.shape[0] - 1 - np.isfinite(AX)[::-1].argmax(axis=0) 

k enthält die Zeilenindizes, wo die endgültigen Werte auftreten. Für jede Spalte gibt es eine Spalte, daher lauten die entsprechenden Spaltenindizes einfach np.arange(AX.shape[1]).

In [101]: last_vals = AX[k, np.arange(AX.shape[1])] 

last_vals ist die eindimensionale Anordnung der letzten nicht-nan-Werte in jeder Spalte, es sei denn, eine Spalte alle nan, wobei in diesem Fall der Wert in last_vals ist auch nan:

In [102]: last_vals 
Out[102]: array([-0.07626913, -0.9450442 ,   nan, 0.7364234 , 0.83810714]) 

Um die nicht-nan Werte in last_vals zu beseitigen, können Sie indizieren mit np.isfinite(last_vals):

In [103]: last_vals[np.isfinite(last_vals)] 
Out[103]: array([-0.07626913, -0.9450442 , 0.7364234 , 0.83810714]) 
+0

Dies scheint echte genial! Ich werde mich langsam durch die einzelnen Schritte bewegen, um sicherzustellen, dass ich jeden Teil verstehe. Da ist viel los :) –

+0

Ich schätze das "Akzeptieren", aber es war wahrscheinlich zu früh. Es gibt ziemlich viele clevere Numpythonisten, die die Stackoverflow-Fragen im Auge behalten, und Sie erhalten wahrscheinlich eine Vielzahl von Antworten, wenn Sie eine Weile warten, bevor Sie eine akzeptieren. –

+0

Gut, ich bin ziemlich neu auf dieser Seite und wusste nicht, dass das die Motivation für Antworten war. Bezeichnen die Leute weiterhin akzeptierte Antworten? –

Verwandte Themen