Numpy donde funcionan múltiples condiciones

Tengo una serie de distancias llamadas dists. Quiero seleccionar dists que están entre dos valores. Escribí la siguiente línea de código para hacer eso:

dists[(np.where(dists >= r)) and (np.where(dists <= r + dr))] 

Sin embargo, esto selecciona sólo para la condición

  (np.where(dists <= r + dr)) 

Si hago los comandos de forma secuencial utilizando una variable temporal, funciona bien. ¿Por qué no funciona el código anterior y cómo lo hago funcionar?

Aclamaciones

La mejor manera en su caso particular sería simplemente cambiar sus dos criterios a un criterio:

 dists[abs(dists - r - dr/2.) <= dr/2.] 

Solo crea una matriz booleana, y en mi opinión es más fácil de leer porque dice, ¿ está dist dentro de un dr o r ? (Aunque redefiniré r para ser el centro de su región de interés en lugar del principio, entonces r = r + dr/2. ) r = r + dr/2. Pero eso no responde a su pregunta.


La respuesta a tu pregunta:
En realidad, no necesita where si solo intenta filtrar los elementos de dists que no se ajustan a sus criterios:

 dists[(dists >= r) & (dists <= r+dr)] 

Porque el & te dará un elemento and (los paréntesis son necesarios).

O bien, si desea usar el sitio where por alguna razón, puede hacer:

  dists[(np.where((dists >= r) & (dists <= r + dr)))] 

Por qué:
La razón por la que no funciona es porque np.where devuelve una lista de índices, no una matriz booleana. Está intentando obtener and entre dos listas de números, que por supuesto no tienen los valores de True / False que espera. Si a y b son ambos valores True , entonces a and b devuelven b . Así que decir algo como [0,1,2] and [2,3,4] solo te dará [2,3,4] . Aquí está en acción:

 In [230]: dists = np.arange(0,10,.5) In [231]: r = 5 In [232]: dr = 1 In [233]: np.where(dists >= r) Out[233]: (array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),) In [234]: np.where(dists <= r+dr) Out[234]: (array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),) In [235]: np.where(dists >= r) and np.where(dists <= r+dr) Out[235]: (array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),) 

Lo que esperabas para comparar era simplemente la matriz booleana, por ejemplo

 In [236]: dists >= r Out[236]: array([False, False, False, False, False, False, False, False, False, False, True, True, True, True, True, True, True, True, True, True], dtype=bool) In [237]: dists <= r + dr Out[237]: array([ True, True, True, True, True, True, True, True, True, True, True, True, True, False, False, False, False, False, False, False], dtype=bool) In [238]: (dists >= r) & (dists <= r + dr) Out[238]: array([False, False, False, False, False, False, False, False, False, False, True, True, True, False, False, False, False, False, False, False], dtype=bool) 

Ahora puede llamar a np.where en la matriz booleana combinada:

 In [239]: np.where((dists >= r) & (dists <= r + dr)) Out[239]: (array([10, 11, 12]),) In [240]: dists[np.where((dists >= r) & (dists <= r + dr))] Out[240]: array([ 5. , 5.5, 6. ]) 

O simplemente indexe la matriz original con la matriz booleana usando una indexación elegante

 In [241]: dists[(dists >= r) & (dists <= r + dr)] Out[241]: array([ 5. , 5.5, 6. ]) 

Dado que la respuesta aceptada explicó el problema muy bien. También puede usar varias funciones lógicas, que son más adecuadas aquí para múltiples condiciones:

 np.where(np.logical_and(np.greater_equal(dists,r),np.greater_equal(dists,r + dr))) 

Tratar:

 np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0]) 

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

 >>> # function which returns True when constraints are satisfied. >>> func = lambda d: d >= r and d<= (r+dr) >>> >>> # Apply constraints element-wise to the dists array. >>> result = np.vectorize(func)(dists) >>> >>> result = np.where(result) # Get output. 

También puede usar np.argwhere lugar de np.where para una salida clara. Pero esa es tu llamada 🙂

Espero eso ayude.

He resuelto este sencillo ejemplo.

 import numpy as np ar = np.array([3,4,5,14,2,4,3,7]) print [X for X in list(ar) if (X >= 3 and X <= 6)] >>> [3, 4, 5, 4, 3] 

Esto debería funcionar:

 dists[((dists >= r) & (dists <= r+dr))] 

La forma más elegante ~~