python3 - Intercambia rebanadas de matrices Numpy
python3 numpy (4)
Encuentro esto el más simple:
a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:, 0, 0].copy() #swap
Comparación de tiempo:
%timeit a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:, 0, 0].copy() #swap
The slowest run took 10.79 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 1.75 µs per loop
%timeit t = np.copy(a[:,0,0]); a[:,0,0] = b[:,0,0]; b[:,0,0] = t
The slowest run took 10.88 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 2.68 µs per loop
Me encanta la forma en que python está manejando los cambios de variables: a, b, = b, a
y me gustaría usar esta funcionalidad para intercambiar valores entre las matrices, no solo de a una, sino de varias (sin usar una variable de temperatura). Esto no es lo que esperaba (esperaba que ambas entradas a lo largo de la tercera dimensión cambiarían por ambas):
import numpy as np
a = np.random.randint(0, 10, (2, 3,3))
b = np.random.randint(0, 10, (2, 5,5))
# display before
a[:,0, 0]
b[:,0,0]
a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:,0,0] #swap
# display after
a[:,0, 0]
b[:,0,0]
¿Alguien tiene alguna idea? Por supuesto, siempre puedo introducir una variable adicional, pero me preguntaba si había una forma más elegante de hacerlo.
Esto funcionará
a[:,0,0], b[:, 0, 0] = b[:, 0, 0].copy(), a[:, 0, 0].copy()
Python interpreta correctamente el código como si usara variables adicionales, por lo que el código de intercambio es equivalente a:
t1 = b[:,0,0]
t2 = a[:,0,0]
a[:,0,0] = t1
b[:,0,0] = t2
Sin embargo, ¡incluso este código no intercambia valores correctamente! Esto se debe a que las slices Numpy no copian los datos con entusiasmo, sino que crean vistas en los datos existentes. Las copias se realizan solo en el punto en el que se asignan las divisiones, pero cuando se intercambia, la copia sin un buffer intermedio destruye sus datos. Es por eso que no solo necesita una variable adicional, sino también un búfer numpy adicional, cuya sintaxis general de Python no puede saber nada. Por ejemplo, esto funciona como se esperaba:
t = np.copy(a[:,0,0])
a[:,0,0] = b[:,0,0]
b[:,0,0] = t
La respuesta de user4815162342 es de hecho la respuesta "correcta". Pero si realmente buscas un proyecto de una sola línea, considera esto:
a[arange(2),0,0], b[arange(2), 0, 0] = b[arange(2), 0, 0], a[arange(2),0,0] #swap
Sin embargo, esto es significativamente menos eficiente:
In [12]: %timeit a[arange(2),0,0], b[arange(2), 0, 0] = b[arange(2), 0, 0], a[arange(2),0,0]
10000 loops, best of 3: 32.2 µs per loop
In [13]: %timeit t = np.copy(a[:,0,0]); a[:,0,0] = b[:,0,0]; b[:,0,0] = t
The slowest run took 4.14 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 13.3 µs per loop
(pero observe la nota sobre "la ejecución más lenta" ... si intenta llamar a% timeit con "-n 1 -r 1", verá resultados más comparables, aunque con mi solución siendo ~ 50% más lenta) demostrando eso sí, el almacenamiento en caché está afectando los tiempos)