2015-02-17 14 views
14

Ich habe ein 1D Array von Werten, die monoton (sagen wir abnehmend) sein soll, aber es gibt zufällige Regionen, wo der Wert mit Index zunimmt.Machen Sie ein numply Array monoton ohne eine Python-Schleife

Ich brauche ein Array, bei dem jede Region durch einen direkt davor liegenden Wert ersetzt wird, so dass das resultierende Array sortiert wird.

Also, wenn gegeben Array ist:

a = np.array([10.0, 9.5, 8.0, 7.2, 7.8, 8.0, 7.0, 5.0, 3.0, 2.5, 3.0, 2.0]) 

ich das Ergebnis

b = np.array([10.0, 9.5, 8.0, 7.2, 7.2, 7.2, 7.0, 5.0, 3.0, 2.5, 2.5, 2.0]) 

Hier ist eine grafische Darstellung sein soll:

example

Ich weiß, wie es zu erreichen mit einer Python-Schleife, aber gibt es eine Möglichkeit, dies mit NumPy zu tun Maschinen?

Python-Code für Klarheit:

b = np.array(a) 
for i in range(1, b.size): 
    if b[i] > b[i-1]: 
     b[i] = b[i-1] 
+0

Warum die Sorge für "ohne eine Schleife"? Ob Sie eine explizite Schleife schreiben oder die Schleife in einer importierten Funktion von einem Modul/Paket ausgeführt wird, ist immer noch vorhanden. Es gibt nicht viele Möglichkeiten, etwas mit einer Reihe von Werten zu tun, die keine Schleife enthalten, es sei denn, Sie möchten die gesamte Schleife vollständig in eine lineare Abfolge von Operationen abwickeln, was aus verschiedenen Gründen hässlich ist - Portabilität, Flexibilität , Code-Größe, etc ... – twalberg

+0

@ twalberg Ich denke, es ist üblich zu versuchen, Python-Schleifen bei der Verwendung von NumPy zu vermeiden, weil die Leistung verbessert wird, wenn die Iteration innerhalb der Funktionen in C durchgeführt wird. Es passiert auch oft, dass der Code ist kürzerer Reiniger. –

+0

Das ist ein gültiger Punkt beim Arbeiten mit großen Datensätzen. In diesem Beispiel (und ohne Hinweis darauf, dass das "echte" Problem um Größenordnungen größer ist) denke ich, dass die Python-Liste in eine Datenstruktur umgewandelt werden muss, an der die C-Schleife arbeiten kann, und dann wieder in sie konvertiert wird die richtige Python-Datenstruktur macht wahrscheinlich keinen Gewinn mehr möglich, indem nicht nur eine Python-Schleife verwendet wird, um über ein Dutzend Einträge zu iterieren ... Besser zu bestätigen, dass die Schleife ein Problem ist, bevor sie blind versucht, sie zu eliminieren ... – twalberg

Antwort

16

Sie können np.minimum.accumulate verwenden, um die Minimalwerte zu sammeln, wie Sie durch das Feld bewegen:

>>> np.minimum.accumulate(a) 
array([ 10. , 9.5, 8. , 7.2, 7.2, 7.2, 7. , 5. , 3. , 
     2.5, 2.5, 2. ]) 

An jedem Element im Array, liefert diese Funktion die Mindestwert bisher gesehen. Wenn Sie möchten, dass ein Array monoton zunimmt, können Sie np.maximum.accumulate verwenden.

Viele andere universelle Funktionen in NumPy verfügen über eine accumulate-Methode zum Simulieren von Schleifen durch ein Array, wobei die Funktion auf jedes Element angewendet wird und die zurückgegebenen Werte in einem Array derselben Größe gesammelt werden.

+1

Wow. Ich wusste nichts von '.akkumulieren'! Das ist sehr nah an Python2 'reduce' (oder Python3' functools.reduce'), bin ich richtig? –

+1

Es ist sehr ähnlich - "akkumulieren" speichert das Ergebnis der Operation für jedes Element, das ein Array der gleichen Länge zurückgibt, während die Unfunc's ['reduce'] (http://docs.scipy.org/doc/numpy/reference/) generated/numpy.ufunc.reduce.html) Methode zeigt nur das Endergebnis (kollabiert das Array). –

+0

Oh ja, du hast Recht."Reduzieren" würde also im Grunde das letzte Element dessen zurückgeben, was "akkumulieren" zurückgibt. –

Verwandte Themen