Meest efficiënte manier om een numpy array om te keren

Geloof het of niet, na het profileren van mijn huidige code, nam de repetitieve bewerking van numpy array-reversie een gigantisch deel van de looptijd in beslag. Wat ik nu heb, is de gemeenschappelijke view-based methode:

reversed_arr = arr[::-1]

Is er een andere manier om het efficiënter te doen, of is het slechts een illusie van mijn obsessie met onrealistische numpy prestaties?


Antwoord 1, autoriteit 100%

Wanneer u reversed_arrmaakt, maakt u een weergave in de originele array. U kunt dan de oorspronkelijke array wijzigen en de weergave wordt bijgewerkt om de wijzigingen weer te geven.

Maakt u de weergave vaker opnieuw dan nodig is? Je zou zoiets als dit moeten kunnen doen:

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

Ik ben geen numpy-expert, maar dit lijkt de snelste manier om dingen in numpy te doen. Als dit is wat je al doet, denk ik niet dat je het kunt verbeteren.

P.S. Geweldige discussie over numpy views hier:

Kijk op een numpy-array?


Antwoord 2, autoriteit 27%

Zoals hierboven vermeld,

a[::-1]

creëert eigenlijk alleen een weergave, dus het is een bewerking met een constante tijd (en als zodanig duurt het niet langer naarmate de array groeit). Als u de array aaneengesloten wilt hebben (bijvoorbeeld omdat u er veel vectorbewerkingen mee uitvoert), is ascontiguousarrayongeveer net zo snel als flipud/fliplr:


Code om de plot te genereren:

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)",
)

Antwoord 3, autoriteit 16%

Omdat dit nog niet als beantwoord lijkt te zijn… Het antwoord van Thomas Arildsen zou het juiste moeten zijn: gebruik gewoon

np.flipud(your_array) 

als het een 1d-array is (kolomarray).

Met matrizes doen

fliplr(matrix)

als u rijen wilt omkeren en flipud(matrix)als u kolommen wilt omdraaien. Het is niet nodig om van uw 1D-kolomarray een tweedimensionale rijarray (matrix met één laag Geen) te maken en deze vervolgens om te draaien.


Antwoord 4, autoriteit 14%

np.fliplr()draait de array van links naar rechts.

Houd er rekening mee dat u voor 1d-arrays een beetje om de tuin moet leiden:

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

Antwoord 5

Ik zal uitbreiden op het eerdere antwoord over np.fliplr(). Hier is een code die toont aan het bouwen van een 1D-array, het transformeren in een 2D-array, het omdraaien en vervolgens terug te zetten in een 1D-array. time.clock()Wordt gebruikt om de tijd te houden, die wordt gepresenteerd in termen van seconden.

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

Met niet-ingevoerde afdrukrekening:

[2 1 0]
0.00203907123594

met afdrukverklaring opgenomen:

5.59799927506e-05

Dus, in termen van efficiëntie, denk ik dat fatsoenlijk is. Voor degenen onder u die het leuk vinden om het in één lijn te doen, is dit formulier.

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

Antwoord 6

breiden uit wat anderen hebben gezegd, ik zal een kort voorbeeld geven.

Als u een 1D-array hebt …

>>> 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])

Maar als u met een 2D-array werkt …

>>> 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]])

Dit keert de Matrix niet echt om.

Moet np.flip gebruiken om de elementen daadwerkelijk om te keren

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

Als u de elementen van een matrix één voor één wilt afdrukken, gebruik dan plat samen met omdraaien

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

Antwoord 7

De op segmentnotatie gebaseerde analoog aan np.flip zou [::-1,::-1] zijn

a = np.array([[1., 2.], [3., 4.], [5, 6]])
print(a)
out: [[1. 2.]
      [3. 4.]
      [5. 6.]]
b=a[::-1,::-1]
print(b)
out: [[1. 2.]
      [3. 4.]
      [5. 6.]]

Antwoord 8

Om het te laten werken met negatieve getallen en een lange lijst, kun je het volgende doen:

b = numpy.flipud(numpy.array(a.split(),float))

Waar flipud is voor 1d arra

Other episodes