2010-06-12 14 views
80

Supongamos que tengo una matriz numpy x = [5, 2, 3, 1, 4, 5], y = ['f', 'o', 'o', 'b', 'a', 'r']. Quiero seleccionar los elementos en y correspondientes a los elementos de x que son mayores que 1 y menor que 5.Numpy array, ¿cómo seleccionar índices que satisfagan múltiples condiciones?

Probé

x = array([5, 2, 3, 1, 4, 5]) 
y = array(['f','o','o','b','a','r']) 
output = y[x > 1 & x < 5] # desired output is ['o','o','a'] 

pero esto no funciona. ¿Cómo haría esto?

Respuesta

134

Su expresión funciona si se agrega paréntesis:

>>> y[(1 < x) & (x < 5)] 
array(['o', 'o', 'a'], 
     dtype='|S1') 
+0

Eso es bueno .. vecMask = 1 Ralf

+1

omg esto es tan raro –

+0

@JennyYueJin: Sucede debido a la precedencia. (Bitwise) '&' tiene una precedencia mayor que '<' and '>', que a su vez tienen una precedencia mayor que (lógico) 'y'. 'x> 1 yx <5' evacua las desigualdades primero y luego la conjunción lógica; 'x> 1 & x <5' evalúa la conjunción bit a bit de' 1' y (los valores en) 'x', luego las desigualdades. '(x> 1) & (x <5)' fuerza primero las desigualdades para evaluar, de modo que todas las operaciones se realizan en el orden deseado y los resultados están bien definidos. [Consulte los documentos aquí.] (Https://docs.python.org/3/reference/expressions.html#operator-precedence) – calavicci

23

OMI OP en realidad no quieren np.bitwise_and() (aka &) pero en realidad quiere np.logical_and() porque están comparando los valores lógicos como True y False - ver este SO publicar en logical vs. bitwise para ver la diferencia.

>>> x = array([5, 2, 3, 1, 4, 5]) 
>>> y = array(['f','o','o','b','a','r']) 
>>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a'] 
>>> output 
array(['o', 'o', 'a'], 
     dtype='|S1') 

Y equivale manera de hacerlo es con np.all() estableciendo el argumento axis adecuadamente.

>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a'] 
>>> output 
array(['o', 'o', 'a'], 
     dtype='|S1') 

por los números:

>>> %timeit (a < b) & (b < c) 
The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 1.15 µs per loop 

>>> %timeit np.logical_and(a < b, b < c) 
The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached. 
1000000 loops, best of 3: 1.17 µs per loop 

>>> %timeit np.all([a < b, b < c], 0) 
The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 5.06 µs per loop 

así que usar np.all() es más lento, pero & y logical_and son aproximadamente la misma.

+7

Debe tener un poco de cuidado sobre cómo hablar sobre lo que se evalúa. Por ejemplo, en 'output = y [np.logical_and (x> 1, x <5)]', 'x <5' * es * evaluado (posiblemente creando una enorme matriz), aunque es el segundo argumento, porque eso la evaluación ocurre fuera de la función. IOW, 'logical_and' pasa dos argumentos ya evaluados. Esto es diferente del caso habitual de 'a y b', en el que' b' no se evalúa si 'a' es truelike. – DSM

+12

no hay diferencia entre bitwise_and() y logical_and() para matrices booleanas – jfs

14

Agregue un detalle a @JF. de las respuestas de @ Marcos Mikofski Sebastián y:
Si se quiere obtener los índices correspondientes (en lugar de los valores reales de la matriz), el siguiente código harán:

Para satisfacer múltiples (todas) las condiciones:

select_indices = np.where(np.logical_and(x > 1, x < 5)) # 1 < x <5 

para múltiples que satisfacen (o) condiciones:

select_indices = np.where(np.logical_or(x < 1, x > 5)) # x <1 or x >5 
+0

Tenga en cuenta que numpy.where no solo devolverá una matriz de los índices, sino que devolverá una tupla (la salida de condition.nonzero()) que contiene matrices - en este caso, '(la matriz de índices que desea,)', necesitará 'select_indices = np.where (...) [0]' para obtener el resultado que desea y espera. – calavicci

1

En realidad, yo lo haría de esta manera:

L1 es la lista de índice de elementos que cumplen la condición 1; (tal vez puede usar somelist.index(condition1) o np.where(condition1) para obtener L1.)

De manera similar, obtiene L2, una lista de elementos que cumplen la condición 2;

Luego se encuentra la intersección usando intersect(L1,L2).

También puede encontrar la intersección de varias listas si obtiene múltiples condiciones para satisfacer.

Luego puede aplicar el índice en cualquier otra matriz, por ejemplo, x.

1

Me gusta usar np.vectorize para tales tareas. Considere lo siguiente:

>>> # Arrays 
>>> x = np.array([5, 2, 3, 1, 4, 5]) 
>>> y = np.array(['f','o','o','b','a','r']) 

>>> # Function containing the constraints 
>>> func = np.vectorize(lambda t: t>1 and t<5) 

>>> # Call function on x 
>>> y[func(x)] 
>>> array(['o', 'o', 'a'], dtype='<U1') 

La ventaja es que puede agregar muchos más tipos de restricciones en la función vectorizada.

Espero que ayude.

Cuestiones relacionadas