En un programa pylab (que probablemente podría ser un programa MATLAB también) tengo una matriz numpy de números que representan distancias: d[t]
es la distancia en el momento t
(y el intervalo de tiempo de mis datos es len(d)
unidades de tiempo).hallazgo longitud de las secuencias de valores idénticos en una matriz numpy (codificación de longitud de ejecución)
Los eventos que me interesan son cuando la distancia está por debajo de un cierto umbral, y quiero calcular la duración de estos eventos. Es fácil obtener una matriz de booleanos con b = d<threshold
, y el problema se reduce a calcular la secuencia de las longitudes de las palabras True-only en b
. Pero no sé cómo hacerlo de manera eficiente (es decir, usando primitivas numpy), y recurrí a caminar la matriz y hacer detección manual de cambios (es decir, inicializar el contador cuando el valor pasa de False a True, aumentar el contador siempre que el valor sea True y saca el contador a la secuencia cuando el valor vuelve a False). Pero esto es tremendamente lento.
Cómo detectar eficazmente ese tipo de secuencias en matrices numpy?
A continuación se muestra un código Python que ilustra mi problema: el cuarto punto tarda mucho tiempo en aparecer (si no es así, aumentar el tamaño de la matriz)
from pylab import *
threshold = 7
print '.'
d = 10*rand(10000000)
print '.'
b = d<threshold
print '.'
durations=[]
for i in xrange(len(b)):
if b[i] and (i==0 or not b[i-1]):
counter=1
if i>0 and b[i-1] and b[i]:
counter+=1
if (b[i-1] and not b[i]) or i==len(b)-1:
durations.append(counter)
print '.'
Hmmmmm ... ese último parece familiar. ;) – gnovice
¡Muchas gracias! La solución diff/where es exactamente lo que tenía en mente (sin mencionar que es aproximadamente 10 veces más rápida que las otras soluciones). Llámalo "no demasiado inteligente" si quieres, pero ojalá fuera lo suficientemente inteligente como para idearlo :-) – Gyom
@gnovice, no hago matlab (suficientemente gracioso mi hija, ahora candidata a doctorado en avanzado la ingeniería de radio, sí ;-), pero ahora, al ver tu respuesta, veo las analogías: obtengo el final de las carreras menos el inicio de las carreras, obtengo esas al ubicar <0 and > 0 en las diferencias, y relleno el bits con ceros para asegurarse de que todas las run-of-ones terminen. ¡Adivina que no hay tantas maneras de eliminar este problema de "duración de ejecución"!) –