La manière la plus efficace d'inverser un tableau de numpy

croyez-le ou non, après avoir établi le profil de mon code actuel, le fonctionnement répétitif de la réversion des réseaux numpy a englouti une partie énorme du temps de fonctionnement. Ce que j'ai en ce moment est la méthode basée sur une vue commune:

reversed_arr = arr[::-1]

est-ce qu'il y a un autre moyen de le faire plus efficacement, ou est-ce juste une illusion de mon obsession pour une performance irréaliste?

208
demandé sur nye17 2011-07-21 08:58:24

6 réponses

lorsque vous créez reversed_arr vous créez une vue dans le tableau original. Vous pouvez alors changer le tableau original, et la vue sera mise à jour pour refléter les changements.

est-ce que vous recréez la vue plus souvent que vous n'en avez besoin? Vous devriez pouvoir faire quelque chose comme ceci:

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

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

Je ne suis pas un expert en numpy, mais il semble que ce serait le moyen le plus rapide de faire les choses à numpy. Si c'est ce que vous faites déjà, je ne pensez pas que vous pouvez l'améliorer.

P. S., Grande discussion de numpy vues ici:

Vue sur un numpy array?

177
répondu steveha 2017-05-23 12:26:36

np.fliplr() renverse le tableau de gauche à droite.

notez que pour les tableaux 1d, vous devez le piéger un peu:

arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]
34
répondu tooty44 2016-05-11 17:17:18

parce que cela ne semble pas encore marqué comme répondu... La réponse de Thomas Arildsen devrait être la bonne: il suffit d'utiliser

np.flipud(your_array) 

s'il s'agit d'un tableau 1d (colonne array).

Avec matrizes faire

fliplr(matrix)

si vous voulez inverser les lignes et les flipud(matrix) si vous voulez retourner les colonnes. Pas besoin de faire de votre tableau de colonne 1d un tableau de ligne 2dimensionnel (matrice avec une couche Aucune) et ensuite de le retourner.

30
répondu zauberfein 2017-07-21 11:28:30

comme mentionné ci-dessus, a[::-1] ne crée vraiment qu'une vue, donc c'est une opération à temps constant (et en tant que tel ne prend pas plus longtemps que le tableau se développe). Si vous avez besoin du tableau pour être contigu (par exemple parce que vous effectuez de nombreuses opérations vectorielles avec lui), ascontiguousarray est à peu près aussi rapide que flipup / fliplr :

enter image description here


Code pour générer le plot:

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,
    )
22
répondu Nico Schlömer 2018-06-19 14:23:06

je vais développer la réponse précédente au sujet de np.fliplr() . Voici un code qui montre comment construire un tableau 1d, le transformer en tableau 2d, le retourner, puis le convertir de nouveau en tableau 1D. time.clock() sera utilisé pour garder le temps, qui est présenté en termes de secondes.

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

Avec l'imprimé de déclaration sans commentaire:

[2 1 0]
0.00203907123594

Avec l'instruction print commenté:

5.59799927506e-05

So, en termes d'efficacité, je pense que c'est décent. Pour ceux d'entre vous qui aiment le faire dans une ligne, voici cette forme.

np.fliplr(np.atleast_2d(np.array(range(3))))[0]
3
répondu M. Murphy 2016-05-11 17:18:06

pour qu'il fonctionne avec des nombres négatifs et une longue liste, vous pouvez faire ce qui suit:

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

où flipud est pour 1D arra

0
répondu Boris Stoyanov 2017-04-19 08:51:16