2012-06-05 12 views
5

Dada una matriz,Reemplazar subarreglos en numpy

>>> n = 2 
>>> a = numpy.array([[[1,1,1],[1,2,3],[1,3,4]]]*n) 
>>> a 
array([[[1, 1, 1], 
     [1, 2, 3], 
     [1, 3, 4]], 

     [[1, 1, 1], 
     [1, 2, 3], 
     [1, 3, 4]]]) 

Yo sé que es posible sustituir los valores en forma sucinta como tal,

>>> a[a==2] = 0 
>>> a 
array([[[1, 1, 1], 
     [1, 0, 3], 
     [1, 3, 4]], 

     [[1, 1, 1], 
     [1, 0, 3], 
     [1, 3, 4]]]) 

¿Es posible hacer lo mismo para toda una fila (último eje) en la matriz? Sé que a[a==[1,2,3]] = 11 funcionará y reemplazará todos los elementos de los subarreglos coincidentes por 11, pero me gustaría sustituirlo por un subcampo diferente. Mi intuición me dice que escriba lo siguiente, pero se produce un error,

>>> a[a==[1,2,3]] = [11,22,33] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: array is not broadcastable to correct shape 

En resumen, lo que me gustaría conseguir es:

array([[[1, 1, 1], 
     [11, 22, 33], 
     [1, 3, 4]], 

     [[1, 1, 1], 
     [11, 22, 33], 
     [1, 3, 4]]]) 

... yn es, por supuesto, en en general, mucho más grande que 2, y los otros ejes también son más grandes que 3, por lo que no quiero repetirlos si no es necesario.


Actualización: El [1,2,3] (o cualquier otra cosa que estoy buscando) no siempre es en el índice 1. Un ejemplo:

a = numpy.array([[[1,1,1],[1,2,3],[1,3,4]], [[1,2,3],[1,1,1],[1,3,4]]]) 

Respuesta

2

Tienes que hacer algo un poco más complicado para lograr lo que quieres.

No puede seleccionar sectores de matrices como tales, pero puede seleccionar todos los índices específicos que desee.

Por lo tanto, primero debe construir una matriz que represente las filas que desea seleccionar. es decir.

data = numpy.array([[1,2,3],[55,56,57],[1,2,3]]) 

to_select = numpy.array([1,2,3]*3).reshape(3,3) # three rows of [1,2,3] 

selected_indices = data == to_select 
# array([[ True, True, True], 
#  [False, False, False], 
#  [ True, True, True]], dtype=bool) 

data = numpy.where(selected_indices, [4,5,6], data) 
# array([[4, 5, 6], 
#  [55, 56, 57], 
#  [4, 5, 6]]) 

# done in one step, but perhaps not very clear as to its intent 
data = numpy.where(data == numpy.array([1,2,3]*3).reshape(3,3), [4,5,6], data) 

numpy.where obras de seleccionar desde el segundo argumento si es verdadero y el tercer argumento si es falso.

Puede usar dónde seleccionar entre 3 tipos de datos diferentes. La primera es una matriz que tiene la misma forma que selected_indices, la segunda es solo un valor en sí misma (como 2 o 7). El primero es el más complicado, ya que puede tener una forma que se puede transmitir en la misma forma que selected_indices. En este caso proporcionamos [1,2,3] que se pueden apilar para obtener una matriz con forma 3x3.

+0

¡Brillante! No pensé en 'dónde'. – Karol

0

Nota seguro si esto es lo que quiere, el ejemplo de código no crea la matriz que dice que hace. Pero:

>>> a = np.array([[[1,1,1],[1,2,3],[1,3,4]], [[1,1,1],[1,2,3],[1,3,4]]]) 
>>> a 
array([[[1, 1, 1], 
     [1, 2, 3], 
     [1, 3, 4]], 

     [[1, 1, 1], 
     [1, 2, 3], 
     [1, 3, 4]]]) 
>>> a[:,1,:] = [[8, 8, 8], [8,8,8]] 
>>> a 
array([[[1, 1, 1], 
     [8, 8, 8], 
     [1, 3, 4]], 

     [[1, 1, 1], 
     [8, 8, 8], 
     [1, 3, 4]]]) 
>>> a[:,1,:] = [88, 88, 88] 
>>> a 
array([[[ 1, 1, 1], 
     [88, 88, 88], 
     [ 1, 3, 4]], 

     [[ 1, 1, 1], 
     [88, 88, 88], 
     [ 1, 3, 4]]]) 
+0

Tienes razón, hubo un error en mi pregunta ... lo resolvió ahora. Su solución funciona para mi ejemplo específico, pero '[1,2,3]' no siempre estará en el índice '1', por lo que' a [:, 1,:] 'no es algo que funcione en general. Tomemos, por ejemplo, esta matriz: 'a = numpy.array ([[[1,1,1], [1,2,3], [1,3,4]], [[1,2,3], [1,1,1], [1,3,4]]]) '. Necesito encontrar los lugares donde '[1,2,3]' ocurre. – Karol

2

Usted puede lograr esto con un rendimiento mucho más alto usando np.all para comprobar si todas las columnas tienen un valor True para su comparación, a continuación, utilizando la máscara creada para reemplazar los valores:

mask = np.all(a==[1,2,3], axis=2) 
a[mask] = [11, 22, 23] 

print(a) 
#array([[[ 1, 1, 1], 
#  [11, 22, 33], 
#  [ 1, 3, 4]], 
# 
#  [[ 1, 1, 1], 
#  [11, 22, 33], 
#  [ 1, 3, 4]]])