webentwicklung-frage-antwort-db.com.de

Die effizienteste Möglichkeit, ein numpy-Array umzukehren

Ob Sie es glauben oder nicht, nachdem Sie meinen aktuellen Code erstellt haben, hat die wiederholte Operation der Numpy-Array-Reversion einen riesigen Teil der Laufzeit gefressen. Was ich jetzt habe, ist die gängige Sichtweise:

reversed_arr = arr[::-1]

Gibt es eine andere Möglichkeit, dies effizienter zu machen, oder ist es nur eine Illusion aus meiner Obsession mit unrealistischer, unpraktischer Performance?

227
nye17

Wenn Sie reversed_arr erstellen, erstellen Sie eine Ansicht im ursprünglichen Array. Sie können dann das ursprüngliche Array ändern und die Ansicht wird entsprechend den Änderungen aktualisiert.

Erstellen Sie die Ansicht öfter neu als nötig? Sie sollten so etwas tun können:

arr = np.array(some_sequence)
reversed_arr = arr[::-1]

do_something(arr)
look_at(reversed_arr)
do_something_else(arr)
look_at(reversed_arr)

Ich bin kein Experten, aber dies scheint der schnellste Weg zu sein, um Dinge in Zahlen zu erledigen. Wenn Sie dies bereits tun, glaube ich nicht, dass Sie es verbessern können.

P.S. Tolle Diskussion über numpy Ansichten hier:

Blick auf ein numpy Array?

196
steveha

np.fliplr() dreht das Array von links nach rechts. 

Beachten Sie, dass Sie für 1d-Arrays einen kleinen Trick benötigen: 

arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]
37
tooty44

Wie bereits erwähnt, erstellt a[::-1] wirklich nur eine Ansicht, dh es ist eine Operation mit konstanter Zeit (und dauert daher nicht länger, wenn das Array wächst). Wenn das Array zusammenhängend sein soll (beispielsweise weil Sie viele Vektoroperationen damit ausführen), ist ascontiguousarray ungefähr so ​​schnell wie flipup/fliplr:

 enter image description here


Code zum Erzeugen des Diagramms:

import numpy
import perfplot


perfplot.show(
    setup=lambda n: numpy.random.randint(0, 1000, n),
    kernels=[
        lambda a: a[::-1],
        lambda a: numpy.ascontiguousarray(a[::-1]),
        lambda a: numpy.fliplr([a])[0]
        ],
    labels=['a[::-1]', 'ascontiguousarray(a[::-1])', 'fliplr'],
    n_range=[2**k for k in range(25)],
    xlabel='len(a)',
    logx=True,
    logy=True,
    )
35
Nico Schlömer

Denn das scheint noch nicht als beantwortet markiert zu sein ... Die Antwort von Thomas Arildsen sollte die richtige sein: einfach nutzen

np.flipud(your_array) 

wenn es sich um ein 1d-Array (Spaltenarray) handelt. 

Mit Matrizen machen 

fliplr(matrix)

wenn Sie Zeilen umkehren möchten und flipud(matrix), wenn Sie Spalten spiegeln möchten. Es ist nicht notwendig, aus Ihrem 1d-Spaltenarray ein zweidimensionales Zeilenarray (Matrix mit einer None-Schicht) zu erstellen und es dann umzukehren.

33
zauberfein

Ich werde auf die frühere Antwort zu np.fliplr() eingehen. Hier ist ein Code, der den Aufbau eines 1d-Arrays demonstriert, es in ein 2D-Array umwandelt, es umkehrt und dann wieder in ein 1d-Array konvertiert. time.clock() wird verwendet, um die Zeit in Sekunden zu halten.

import time
import numpy as np

start = time.clock()
x = np.array(range(3))
#transform to 2d
x = np.atleast_2d(x)
#flip array
x = np.fliplr(x)
#take first (and only) element
x = x[0]
#print x
end = time.clock()
print end-start

Mit Druckausgabe unkommentiert:

[2 1 0]
0.00203907123594

Mit Druckausdruck kommentiert:

5.59799927506e-05

In Bezug auf die Effizienz halte ich das für anständig. Für diejenigen von Ihnen, die es lieben, es in einer Zeile zu tun, ist diese Form hier.

np.fliplr(np.atleast_2d(np.array(range(3))))[0]
3
M. Murphy

Ich werde kurz auf das eingehen, was andere gesagt haben.

Wenn Sie ein 1D-Array haben ...

>>> import numpy as np
>>> x = np.arange(4) # array([0, 1, 2, 3])
>>> x[::-1] # returns a view
Out[1]: 
array([3, 2, 1, 0])

Aber wenn Sie mit einem 2D-Array arbeiten ...

>>> x = np.arange(10).reshape(2, 5)
>>> x
Out[2]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> x[::-1] # returns a view:
Out[3]: array([[5, 6, 7, 8, 9],
               [0, 1, 2, 3, 4]])

Dies kehrt die Matrix nicht wirklich um.

Sollte np.flip verwenden, um die Elemente tatsächlich umzukehren

>>> np.flip(x)
Out[4]: array([[9, 8, 7, 6, 5],
               [4, 3, 2, 1, 0]])

Wenn Sie die Elemente einer Matrix einzeln drucken möchten, verwenden Sie die Option Flat neben Flip

>>> for el in np.flip(x).flat:
>>>     print(el, end = ' ')
9 8 7 6 5 4 3 2 1 0
0
John Mil.