2012-08-24 13 views
22

Me gustaría dividir una matriz numpy para obtener el índice i-ésimo en la última dimensión. Para una matriz 3D, esto sería:Numeración de dimensiones arbitrarias

slice = myarray[:,:,i] 

Pero estoy escribiendo una función donde puedo tomar una serie de medidas arbitrarias, por lo que para una matriz de 4D que necesitaría myarray[:,:,:,i], y así sucesivamente. ¿Hay alguna forma de que pueda obtener esta porción para cualquier matriz sin tener que escribir explícitamente las dimensiones de la matriz?

Respuesta

35

Hay ... o Ellipsis, que hace exactamente esto:

slice = myarray[...,i] 

Elipsis es el objeto pitón, si debe querer usarlo fuera de la notación de corchetes.

+0

Gracias, no sabía de esto. Mi propia respuesta permite rebanadas más genéricas, pero la tuya es realmente genial. – tiago

+0

@tiago De hecho, siempre puedes construir una tupla de corte. > También puedes usar 'Ellipsis' allí ... – seberg

5

En realidad, acabo de encontrar la respuesta. Como se indica en numpy's documentation, esto se puede hacer con el objeto slice. En mi caso particular, esto se hace:

idx = [slice(None)] * (myarray.ndim - 1) + [i] 
my_slice = myarray[idx] 

El slice(None) es equivalente a elegir todos los elementos de ese índice, y el último [i] selecciona un índice específico para la última dimensión.

+0

¡Estaba a punto de sugerir esto, pero en realidad el enfoque de Sebastian es mucho más elegante! Además, no creo que tu código realmente funcione, estás multiplicando una lista con una tupla y luego estás concatenando un índice desnudo sin un objeto 'slice()'. Quizás quiso decir '[slice (None)] * myarray.shape [-1] + [slice (None, i)]' –

+1

@NiklasB. El último '[i]' es correcto, pero la primera parte debe ser '(myarray.ndim - 1)' para el multiplicador si no se usa 'Ellipsis'. – seberg

+0

@Sebastian, tienes razón, probé usando un número y luego olvidé poner len (myarray.shape [: - 1]). Lo arreglé con tu sugerencia. – tiago

2

En términos de rebanar una dimensión arbitraria, las anteriores excelentes respuestas se puede extender a:

indx = [Ellipsis]*myarray.ndim 
indx[slice_dim] = i 
slice = myarray[indx] 

Esto devuelve el rebanada de cualquier dimensión slice_dim - slice_dim = -1 reproduce las respuestas anteriores. Para completar - las dos primeras líneas de la lista anterior se pueden condensar a:

indx = [Ellipsis]*(slice_dim) + [i] + [Ellipsis]*(myarray.ndim-slice_dim-1) 

aunque encuentro la versión anterior más legible.

Cuestiones relacionadas