2011-04-16 8 views

Respuesta

10

Aquí es una aplicación compacta de un iterador como:

def iter1d(a): 
    return itertools.chain.from_iterable(
     numpy.rollaxis(a, axis, a.ndim).reshape(-1, dim) 
     for axis, dim in enumerate(a.shape)) 

esto dará lugar a las submatrices en el orden que dio en su mensaje:

for x in iter1d(a): 
    print x 

grabados

[ 0 12] 
[ 1 13] 
[ 2 14] 
[ 3 15] 
[ 4 16] 
[ 5 17] 
[ 6 18] 
[ 7 19] 
[ 8 20] 
[ 9 21] 
[10 22] 
[11 23] 
[0 4 8] 
[1 5 9] 
[ 2 6 10] 
[ 3 7 11] 
[12 16 20] 
[13 17 21] 
[14 18 22] 
[15 19 23] 
[0 1 2 3] 
[4 5 6 7] 
[ 8 9 10 11] 
[12 13 14 15] 
[16 17 18 19] 
[20 21 22 23] 

El truco aquí es para iterar sobre todos los ejes, y para cada eje remodelar la matriz a una matriz de dos dimensiones de las filas de los cuales son el subarrays unidimensionales desea.

+0

¡Muy bonito! ¡Mucho más elegante (y eficiente) que mi solución! –

+0

¡Solución increíble! – fodon

+0

Intenté enviarle un correo electrónico a la raíz en su dirección web .net listada en su perfil. Si no quieres conectarte, eso está bien. – fodon

0

sus amigos son los slice() objetos, el método de numpy ndarray.__getitem__(), y posiblemente el itertools.chain.from_iterable.

5

Puede haber una manera más eficiente, pero esto debería funcionar ...

import itertools 
import numpy as np 

a = np.arange(24) 
a = a.reshape(2,3,4) 

colon = slice(None) 
dimensions = [range(dim) + [colon] for dim in a.shape] 

for dim in itertools.product(*dimensions): 
    if dim.count(colon) == 1: 
     print a[dim] 

Este rendimientos (estoy dejando un poco trivial de código para imprimir el lado izquierdo de esta ...):

a[0,0,:] --> [0 1 2 3] 
a[0,1,:] --> [4 5 6 7] 
a[0,2,:] --> [ 8 9 10 11] 
a[0,:,0] --> [0 4 8] 
a[0,:,1] --> [1 5 9] 
a[0,:,2] --> [ 2 6 10] 
a[0,:,3] --> [ 3 7 11] 
a[1,0,:] --> [12 13 14 15] 
a[1,1,:] --> [16 17 18 19] 
a[1,2,:] --> [20 21 22 23] 
a[1,:,0] --> [12 16 20] 
a[1,:,1] --> [13 17 21] 
a[1,:,2] --> [14 18 22] 
a[1,:,3] --> [15 19 23] 
a[:,0,0] --> [ 0 12] 
a[:,0,1] --> [ 1 13] 
a[:,0,2] --> [ 2 14] 
a[:,0,3] --> [ 3 15] 
a[:,1,0] --> [ 4 16] 
a[:,1,1] --> [ 5 17] 
a[:,1,2] --> [ 6 18] 
a[:,1,3] --> [ 7 19] 
a[:,2,0] --> [ 8 20] 
a[:,2,1] --> [ 9 21] 
a[:,2,2] --> [10 22] 
a[:,2,3] --> [11 23] 

La clave aquí es que la indexación a con (por ejemplo) a[0,0,:] es equivalente a la indexación de un con a[(0,0,slice(None))]. (Esto es solo un corte genérico de python, nada numpy-specific. Para demostrárselo a usted mismo, puede escribir una clase ficticia con solo __getitem__ e imprimir lo que pasó cuando indexa una instancia de su clase ficticia).

Entonces, lo que queremos es cualquier combinación posible de 0 a nx, 0 a ny, 0 a nz, etc. y un None para cada eje.

Sin embargo, queremos matrices 1D, por lo que necesitamos para filtrar cualquier cosa con más o menos de un None (es decir que no queremos a[:,:,:], a[0,:,:], a[0,0,0] etc).

suerte que tiene cierto sentido, de todos modos ...

Editar: Estoy asumiendo que el orden exacto no importa ... Si necesitas la exacta Orden enumera en su pregunta, usted resulta necesario modificar este ...

+0

@FM - Buen punto, eso es mucho más legible. ¡Gracias! –

+1

@FM: en realidad 'dim.count (None)' parece incluso más legible que 'sum (1 para el elemento en dim si el elemento es None)' :) –

+0

@Sven - ¡Una vez más, excelente punto! Pasé por alto lo obvio, allí ... –

Cuestiones relacionadas