2012-03-05 10 views
5

¿Alguien sabe de una forma (común) más rápida que lineal para encontrar los puntos finales de una propiedad booleana de una matriz.¿Existe una forma más rápida que lineal de encontrar puntos finales de una condición booleana en numpy?

Por ejemplo numpy.nonzero (a) [0] [- 1] es el índice del último elemento no nulo de a (dimensión = 0), y similarmente numpy.nonzero (a) [0] [0] es el índice del primer elemento distinto de cero.

Si sabemos que solo nos importa el primer o el último elemento, podemos usar menos memoria y tener un mejor tiempo de ejecución en común que ejecutar "distinto de cero" como en el ejemplo anterior. Por ejemplo, si nos quedamos con una búsqueda lineal, al menos podemos comenzar por el final apropiado (buscar hacia atrás para encontrar el último valor que coincida con una condición). O podríamos usar una búsqueda binaria (por ejemplo, si el elemento medio coincide con la condición, no es necesario que verifiquemos la primera mitad para encontrar el último elemento donde sea verdadero). Esto parece lo suficientemente común como para que exista una implementación existente pero no he encontrado nada parecido.

+1

La búsqueda binaria no funciona en general. Si el elemento central es "Verdadero", solo tenemos que mirar en la mitad izquierda, eso es cierto. Si el elemento central es 'False', esto no nos dice nada en absoluto. –

Respuesta

7

Puede encontrar el primer elemento verdadero de una matriz booleana usando argmax.

a = np.array([False, False, True, True, True]) 
first_True = a.argmax() 
last_True = len(a) - 1 - a[::-1].argmax() 

Puede utilizar argmin para encontrar los valores falsos, y esto va a ser más rápido y tener menos memoria que el uso distinto de cero, pero esto es lineal en la longitud de a. Si quieres ser más rápido que lineal, debes saber que a está "ordenado", para una matriz booleana que significa que tienes un bloque de False seguido de todos los True. En ese caso, podría utilizar la búsqueda ordenada para encontrar el límite entre el False y el verdadero:

first_True = a.searchsorted(True, 'left') 
+0

¡Buena explicación! (Y perdón por el comentario anterior ... Lo agregué antes de leer su respuesta completa.) –

+0

Buena solución, aunque un poco intuitiva cuando se considera que el comportamiento especial de argmax en matrices booleanas no se menciona en el [documentos] (http : //docs.scipy.org/doc/numpy/reference/generated/numpy.argmax.html). – Trilarion

+0

No hay un comportamiento especial para las matrices booleanas. Los documentos indican claramente que "En caso de múltiples ocurrencias de los valores máximos, se devuelven los índices correspondientes a la primera ocurrencia". –

Cuestiones relacionadas