2011-02-26 23 views
11

Lo que necesito es una forma de obtener "indexación sofisticada" (y = x [[0, 5, 21]]) para devolver una vista en lugar de una copia.¿Puedo obtener una vista de una matriz numpy en índices especificados? (una vista de "indexación sofisticada")

Tengo una matriz, pero quiero poder trabajar con un subconjunto de esta matriz (especificado por una lista de índices) de tal manera que los cambios en este subconjunto también se colocan en los lugares correctos en el gran variedad. Si solo quiero hacer algo con los primeros 10 elementos, solo puedo usar el corte regular y = x [0:10]. Eso funciona muy bien, porque el corte regular devuelve una vista. El problema es si no quiero 0:10, sino un conjunto arbitrario de índices.

¿Hay alguna manera de hacerlo?

Respuesta

12

No creo que haya una forma de evitar esto. Mi entendimiento es que 'indexación elegante' siempre devolverá una copia. La mejor solución que se me ocurre es manipular y y luego usar los mismos índices de fantasía para cambiar los valores de x después:

ii = [0, 5, 21] 
y = x[ii] 
<manipulate y> 
x[ii] = y 
+4

Usted vencer yo a eso. Lo único que iba a agregar era esto: http://projects.scipy.org/numpy/ticket/224 Indicó que esto no es probable que cambie. – Paul

+1

Oh si este tipo de asignación a la matriz indexada (x [ii] = y) funciona, entonces eso hace lo que necesito, supongo. – Eskil

+0

@Eskil Esto se debe a que 'x [ii] = y' invoca' x .__ setitem __ (ii, y) 'por lo que no hay copia involucrada aunque haya usado una matriz de índice. Es cierto que 'x [ii]' devuelve una copia, pero esto invoca 'x .__ getitem __ (ii)' y es una historia diferente. –

2

Sólo puede hacer:

y = x[[0,1,4]] 
func(y) 
x[[0,1,4]] = y 

no creo puedes obtener vistas con una indexación sofisticada. Es posible que no desee, ya que creo que la indexación de fantasía es bastante lenta, debería ser más rápido simplemente copiar los datos una vez.

0

En teoría, podría crear un objeto que desempeña el papel de una "vista de lujo" en otra matriz, y puedo pensar en muchos casos de uso para ella. El problema es que tal objeto no sería compatible con la maquinaria numpy estándar. Todo el código numpy C compilado se basa en datos accesibles como un producto interno de zancadas e índices. Generalizar este código a formatos de diseño de datos fundamentalmente diferentes sería una empresa gigantesca. Para un proyecto que está tratando de enfrentar un desafío en esta línea, revise el Blaze del continuo.

1

Aquí hay una manera posible de simular tener una vista (algo de azúcar sintáctico), evitando las declaraciones de copia explícitas al final usando un 'contexto de vista elegante'. Tendrá que tener cuidado de que su código no modifica la matriz de índice en el contexto

import contextlib 

@contextlib.contextmanager 
def fancy_index_view(arr, inds): 
    # create copy from fancy inds 
    arr_copy = arr[inds] 

    # yield 'view' (copy) 
    yield arr_copy 

    # after context, save modified data 
    arr[inds] = arr_copy 

ahora, el fragmento

import numpy as np 
foo = np.random.random((22,2)) 
row_inds = [0,5,21] 
barview = foo[row_inds] 
barview[::] = 1 
foo[row_inds] = barview 

podría ser reemplazado por

import numpy as np 
foo = np.random.random((22,2)) 
row_inds = [0,5,21] 
with fancy_index_view(foo, row_inds) as barview: 
    barview[::] = 1 
Cuestiones relacionadas