Créalo o no, después de perfilar mi código actual, la operación repetitiva de la reversión de matriz numpy se comió una gran parte del tiempo de ejecución. Lo que tengo ahora es el método común basado en la vista:
reversed_arr = arr[::-1]
¿Hay alguna otra manera de hacerlo de manera más eficiente, o es solo una ilusión de mi obsesión con el rendimiento poco realista?
7 respuestas
Cuando crea reversed_arr
está creando una vista en la matriz original. Luego puede cambiar la matriz original y la vista se actualizará para reflejar los cambios.
¿Vuelve a crear la vista con más frecuencia de la que necesita? Deberías poder hacer algo como esto:
arr = np.array(some_sequence)
reversed_arr = arr[::-1]
do_something(arr)
look_at(reversed_arr)
do_something_else(arr)
look_at(reversed_arr)
No soy un experto numpy, pero parece que sería la forma más rápida de hacer cosas en numpy. Si esto es lo que ya está haciendo, no creo que pueda mejorarlo.
PD Gran discusión de puntos de vista numpy aquí:
Ampliando lo que otros han dicho, daré un breve ejemplo.
Si tienes una matriz 1D ...
>>> 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])
Pero si está trabajando con una matriz 2D ...
>>> 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]])
Esto en realidad no revierte la matriz.
Debería usar np.flip para invertir los elementos
>>> np.flip(x)
Out[4]: array([[9, 8, 7, 6, 5],
[4, 3, 2, 1, 0]])
Si desea imprimir los elementos de una matriz uno por uno, use plano junto con flip
>>> for el in np.flip(x).flat:
>>> print(el, end = ' ')
9 8 7 6 5 4 3 2 1 0
Porque esto parece no estar marcado como respondido todavía ... La respuesta de Thomas Arildsen debería ser la correcta: solo use
np.flipud(your_array)
Si es una matriz 1d (matriz de columnas).
Con matrices hacer
fliplr(matrix)
Si desea revertir filas y flipud(matrix)
si desea voltear columnas. No es necesario hacer que su matriz de columnas 1d sea una matriz de filas bidimensional (matriz con una capa None) y luego voltearla.
Como se mencionó anteriormente, a[::-1]
realmente solo crea una vista, por lo que es una operación de tiempo constante (y como tal no toma más tiempo a medida que crece la matriz). Si necesita que la matriz sea contigua (por ejemplo, porque está realizando muchas operaciones vectoriales con ella), ascontiguousarray
es casi tan rápido como flipup
/ fliplr
:
Código para generar la trama:
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,
)
np.fliplr()
voltea la matriz de izquierda a derecha.
Tenga en cuenta que para las matrices 1d, debe engañarlo un poco:
arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]
Ampliaré la respuesta anterior sobre np.fliplr()
. Aquí hay un código que demuestra la construcción de una matriz 1d, transformándola en una matriz 2d, volteándola y luego convirtiéndola nuevamente en una matriz 1d. time.clock()
se usará para mantener el tiempo, que se presenta en términos de segundos.
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
Con la declaración de impresión sin comentar:
[2 1 0]
0.00203907123594
Con la declaración impresa comentada:
5.59799927506e-05
Entonces, en términos de eficiencia, creo que es decente. Para aquellos de ustedes que aman hacerlo en una línea, aquí está esa forma.
np.fliplr(np.atleast_2d(np.array(range(3))))[0]
Para que funcione con números negativos y una larga lista, puede hacer lo siguiente:
b = numpy.flipud(numpy.array(a.split(),float))
Donde flipud es para 1d array
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.