2012-05-21 19 views
6

Quiero comprobar si un NumPyArray tiene valores que están en un conjunto, y si es así establecer esa área en una matriz = 1. Si no se establece un keepRaster = 2.Comprueba si los valores de un conjunto están en una matriz numpy en python

numpyArray = #some imported array 
repeatSet= ([3, 5, 6, 8]) 

confusedRaster = numpyArray[numpy.where(numpyArray in repeatSet)]= 1 

Rendimiento:

<type 'exceptions.TypeError'>: unhashable type: 'numpy.ndarray' 

¿hay una forma de bucle a través de él?

for numpyArray 
     if numpyArray in repeatSet 
      confusedRaster = 1 
     else 
      keepRaster = 2 

Para aclarar y pedir un poco más ayuda:

Lo que estoy tratando de llegar, y actualmente estoy haciendo, está poniendo una entrada de trama en una matriz. Necesito leer valores en la matriz de 2-d y crear otra matriz basada en esos valores. Si el valor de la matriz está en un conjunto, el valor será 1. Si no está en un conjunto, el valor se derivará de otra entrada, pero diré 77 por ahora. Esto es lo que estoy usando actualmente. Mi entrada de prueba tiene aproximadamente 1500 filas y 3500 columnas. Siempre se congela a alrededor de fila 350.

for rowd in range(0, width): 
    for cold in range (0, height): 
     if numpyarray.item(rowd,cold) in repeatSet: 
      confusedArray[rowd][cold] = 1 
     else: 
      if numpyarray.item(rowd,cold) == 0: 
       confusedArray[rowd][cold] = 0 
      else: 
       confusedArray[rowd][cold] = 2 

Respuesta

12

En las versiones 1.4 y superiores, numpy proporciona la función in1d.

>>> test = np.array([0, 1, 2, 5, 0]) 
>>> states = [0, 2] 
>>> np.in1d(test, states) 
array([ True, False, True, False, True], dtype=bool) 

Puede usarlo como máscara para la asignación.

>>> test[np.in1d(test, states)] = 1 
>>> test 
array([1, 1, 1, 5, 1]) 

Éstos son algunos de los usos más sofisticados de la sintaxis de indexación y asignación de numpy que creo que se aplicará a su problema. Observe el uso de operadores de bits para reemplazar if lógica basada en:

>>> numpy_array = numpy.arange(9).reshape((3, 3)) 
>>> confused_array = numpy.arange(9).reshape((3, 3)) % 2 
>>> mask = numpy.in1d(numpy_array, repeat_set).reshape(numpy_array.shape) 
>>> mask 
array([[False, False, False], 
     [ True, False, True], 
     [ True, False, True]], dtype=bool) 
>>> ~mask 
array([[ True, True, True], 
     [False, True, False], 
     [False, True, False]], dtype=bool) 
>>> numpy_array == 0 
array([[ True, False, False], 
     [False, False, False], 
     [False, False, False]], dtype=bool) 
>>> numpy_array != 0 
array([[False, True, True], 
     [ True, True, True], 
     [ True, True, True]], dtype=bool) 
>>> confused_array[mask] = 1 
>>> confused_array[~mask & (numpy_array == 0)] = 0 
>>> confused_array[~mask & (numpy_array != 0)] = 2 
>>> confused_array 
array([[0, 2, 2], 
     [1, 2, 1], 
     [1, 2, 1]]) 

Otro enfoque sería utilizar numpy.where, lo que crea una nueva matriz, utilizando los valores del segundo argumento, donde mask es cierto, y los valores de la tercer argumento donde mask es falso. (Al igual que con la asignación, el argumento puede ser un escalar o una matriz de la misma forma que mask.) Esto puede ser un poco más eficiente que el anterior, y es sin duda más concisa:

>>> numpy.where(mask, 1, numpy.where(numpy_array == 0, 0, 2)) 
array([[0, 2, 2], 
     [1, 2, 1], 
     [1, 2, 1]]) 
+0

Hmm, así como yo entiende eso. Si el valor de la prueba está en la lista de estados que es True, que será = 1, de lo contrario será igual a lo que era. Hay una manera de hacer que la salida matriz ([1,0,1,0,0]) – mkmitchell

+0

@mkmitchell, sí, lo tienes. Es similar a la asignación de sectores con listas normales de Python, pero a) usa el sistema de indización más complejo de numpy, yb) sigue la convención numpy de que asignar un escalar a un sector de un conjunto asigna todos los valores del sector a ese valor escalar. – senderle

+0

¿Qué tal si es una matriz 2-D? – mkmitchell

1

Aquí es una forma posible de hacer lo que whant:

numpyArray = np.array([1, 8, 35, 343, 23, 3, 8]) # could be n-Dimensional array 
repeatSet = np.array([3, 5, 6, 8]) 
mask = (numpyArray[...,None] == repeatSet[None,...]).any(axis=-1) 
print mask 
>>> [False True False False False True True] 
Cuestiones relacionadas