index - python iterate numpy array
IteraciĆ³n sobre la dimensiĆ³n arbitraria de numpy.array (4)
¿Hay función para obtener un iterador sobre una dimensión arbitraria de una matriz numpy?
Iterando sobre la primera dimensión es fácil ...
In [63]: c = numpy.arange(24).reshape(2,3,4)
In [64]: for r in c :
....: print r
....:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
Pero iterar sobre otras dimensiones es más difícil. Por ejemplo, la última dimensión:
In [73]: for r in c.swapaxes(2,0).swapaxes(1,2) :
....: print r
....:
[[ 0 4 8]
[12 16 20]]
[[ 1 5 9]
[13 17 21]]
[[ 2 6 10]
[14 18 22]]
[[ 3 7 11]
[15 19 23]]
Estoy haciendo un generador para hacer esto yo mismo, pero me sorprende que no haya una función llamada algo como numpy.ndarray.iterdim (axis = 0) para hacer esto automáticamente.
Entonces, uno puede iterar fácilmente sobre la primera dimensión, como lo ha demostrado. Otra forma de hacer esto para una dimensión arbitraria es usar numpy.rollaxis () para traer la dimensión dada al primero (el comportamiento predeterminado), y luego usar la matriz devuelta (que es una vista, así que esto es rápido) como un iterador .
In [1]: array = numpy.arange(24).reshape(2,3,4)
In [2]: for array_slice in np.rollaxis(array, 1):
....: print array_slice.shape
....:
(2, 4)
(2, 4)
(2, 4)
EDITAR: comentaré que envié un PR a Numpy para abordar esto aquí: https://github.com/numpy/numpy/pull/3262 . El consenso era que esto no era suficiente para agregar a la base de código numpy. Creo que usar np.rollaxis es la mejor manera de hacerlo, y si quieres un interador, envuélvelo en iter ().
Lo que usted propone es bastante rápido, pero la legibilidad se puede mejorar con las formas más claras:
for i in range(c.shape[-1]):
print c[:,:,i]
o, mejor (más rápido, más general y más explícito):
for i in range(c.shape[-1]):
print c[...,i]
Sin embargo, el primer enfoque anterior parece ser aproximadamente el doble de lento que el enfoque swapaxes()
:
python -m timeit -s ''import numpy; c = numpy.arange(24).reshape(2,3,4)'' /
''for r in c.swapaxes(2,0).swapaxes(1,2): u = r''
100000 loops, best of 3: 3.69 usec per loop
python -m timeit -s ''import numpy; c = numpy.arange(24).reshape(2,3,4)'' /
''for i in range(c.shape[-1]): u = c[:,:,i]''
100000 loops, best of 3: 6.08 usec per loop
python -m timeit -s ''import numpy; c = numpy.arange(24).reshape(2,3,4)'' /
''for r in numpy.rollaxis(c, 2): u = r''
100000 loops, best of 3: 6.46 usec per loop
Supongo que esto se debe a que swapaxes()
no copia ningún dato, y porque el manejo de c[:,:,i]
podría hacerse a través de código general (que maneja el caso donde :
se reemplaza por un segmento más complicado) .
Sin embargo c[...,i]
tenga en cuenta que la segunda solución más explícita c[...,i]
es bastante legible y bastante rápida:
python -m timeit -s ''import numpy; c = numpy.arange(24).reshape(2,3,4)'' /
''for i in range(c.shape[-1]): u = c[...,i]''
100000 loops, best of 3: 4.74 usec per loop
Supongo que no hay función. Cuando escribí mi función, terminé tomando la iteración que EOL también sugirió. Para futuros lectores, aquí está:
def iterdim(a, axis=0) :
a = numpy.asarray(a);
leading_indices = (slice(None),)*axis
for i in xrange(a.shape[axis]) :
yield a[leading_indices+(i,)]
Yo usaría lo siguiente:
c = numpy.arange(2 * 3 * 4)
c.shape = (2, 3, 4)
for r in numpy.rollaxis(c, 2):
print(r)
La función rollaxis crea una nueva vista en la matriz. En este caso, está moviendo el eje 2 hacia delante, equivalente a la operación c.transpose(2, 0, 1)
.