¿Puede sugerir una función de módulo de numpy / scipy que pueda encontrar máximos / mínimos locales en una matriz numpy 1D? Obviamente, el enfoque más simple es echar un vistazo a los vecinos más cercanos, pero me gustaría tener una solución aceptada que sea parte de la distribución numpy.
116
Respuestas:
Si está buscando todas las entradas en la matriz 1d
a
más pequeñas que sus vecinas, puede intentarTambién puede suavizar su matriz antes de este paso usando
numpy.convolve()
.No creo que haya una función dedicada a esto.
fuente
<
con>
le dará los máximos locales en lugar de los mínimos[False False]
¿Cuál podría ser el problema aquí?En SciPy> = 0.11
Produce
Tenga en cuenta que estos son los índices de x que son máximos / mínimos locales. Para obtener los valores, intente:
scipy.signal
también proporcionaargrelmax
yargrelmin
para encontrar máximos y mínimos respectivamente.fuente
np.random.random(12)
genera 12 valores aleatorios, se utilizan para demostrar la funciónargrelextrema
.test02=np.array([10,4,4,4,5,6,7,6])
, entonces no funciona. No reconoce los valores consecutivos como mínimos locales.Para curvas sin demasiado ruido, recomiendo el siguiente fragmento de código pequeño:
El
+1
es importante, ya quediff
reduce el número de índice original.fuente
[1, 2, 2, 3, 3, 3, 2, 2, 1]
, el máximo local está obviamente en algún lugar entre los 3 en el medio. Pero si ejecuta las funciones que proporcionó, obtendrá máximos en los índices 2,6 y mínimos en los índices 1,3,5,7, lo que para mí no tiene mucho sentido.+1
lugar denp.diff()
usarnp.gradient()
.Otro enfoque (más palabras, menos código) que puede ayudar:
Las ubicaciones de los máximos y mínimos locales también son las ubicaciones de los cruces por cero de la primera derivada. En general, es mucho más fácil encontrar cruces por cero que encontrar directamente máximos y mínimos locales.
Desafortunadamente, la primera derivada tiende a "amplificar" el ruido, por lo que cuando hay ruido significativo en los datos originales, es mejor usar la primera derivada solo después de que se haya aplicado algún grado de suavizado a los datos originales.
Dado que el suavizado es, en el sentido más simple, un filtro de paso bajo, el suavizado a menudo se realiza mejor (bueno, más fácilmente) mediante el uso de un kernel de convolución, y "modelar" ese kernel puede proporcionar una sorprendente cantidad de capacidad de preservación / mejora de características . El proceso de encontrar un kernel óptimo se puede automatizar usando una variedad de medios, pero lo mejor puede ser la simple fuerza bruta (bastante rápido para encontrar kernels pequeños). Un buen kernel distorsionará (según lo previsto) masivamente los datos originales, pero NO afectará la ubicación de los picos / valles de interés.
Afortunadamente, con bastante frecuencia se puede crear un kernel adecuado mediante un simple SWAG ("conjetura fundamentada"). El ancho del núcleo de suavizado debe ser un poco más ancho que el pico "interesante" esperado más ancho en los datos originales, y su forma se parecerá a ese pico (una ondícula de una sola escala). Para los núcleos que preservan la media (lo que debería ser cualquier buen filtro de suavizado), la suma de los elementos del núcleo debe ser exactamente igual a 1,00, y el núcleo debe ser simétrico con respecto a su centro (lo que significa que tendrá un número impar de elementos.
Dado un kernel de suavizado óptimo (o un pequeño número de kernels optimizados para diferentes contenidos de datos), el grado de suavizado se convierte en un factor de escala para (la "ganancia") del kernel de convolución.
La determinación del grado "correcto" (óptimo) de suavizado (ganancia del núcleo de convolución) se puede incluso automatizar: Compare la desviación estándar de los datos de la primera derivada con la desviación estándar de los datos suavizados. Cómo se usa la relación de las dos desviaciones estándar con los cambios en el grado de suavizado para predecir valores de suavizado efectivos. Unas pocas ejecuciones de datos manuales (que sean verdaderamente representativas) deberían ser todo lo que se necesita.
Todas las soluciones anteriores publicadas anteriormente calculan la primera derivada, pero no la tratan como una medida estadística, ni las soluciones anteriores intentan realizar el suavizado de preservación / mejora de características (para ayudar a que los picos sutiles "salten por encima" del ruido).
Finalmente, las malas noticias: encontrar picos "reales" se convierte en un dolor real cuando el ruido también tiene características que parecen picos reales (ancho de banda superpuesto). La siguiente solución más compleja es generalmente usar un núcleo de convolución más largo (una "apertura de núcleo más amplia") que tenga en cuenta la relación entre picos "reales" adyacentes (como tasas mínimas o máximas para la ocurrencia de picos), o usar múltiples la convolución pasa utilizando núcleos que tienen diferentes anchos (pero solo si es más rápido: es una verdad matemática fundamental que las convoluciones lineales realizadas en secuencia siempre se pueden convolucionar juntas en una sola convolución). Pero a menudo es mucho más fácil encontrar primero una secuencia de kernels útiles (de diferentes anchos) y convertirlos juntos que encontrar directamente el kernel final en un solo paso.
Con suerte, esto proporciona suficiente información para permitir que Google (y quizás un buen texto de estadísticas) llene los vacíos. Realmente desearía tener el tiempo para proporcionar un ejemplo trabajado o un enlace a uno. Si alguien encuentra uno en línea, ¡publíquelo aquí!
fuente
A partir de la versión 1.1 de SciPy, también puede usar find_peaks . A continuación se muestran dos ejemplos tomados de la propia documentación.
Usando el
height
argumento, uno puede seleccionar todos los máximos por encima de un cierto umbral (en este ejemplo, todos los máximos no negativos; esto puede ser muy útil si uno tiene que lidiar con una línea de base ruidosa; si desea encontrar mínimos, simplemente multiplique lo que ingresó por-1
):Otro argumento extremadamente útil es
distance
, que define la distancia mínima entre dos picos:fuente
¿Por qué no utilizar la función integrada de Scipy signal.find_peaks_cwt para hacer el trabajo?
resultados:
Saludos
fuente
Actualización: no estaba contento con el degradado, así que lo encontré más confiable de usar
numpy.diff
. Por favor avíseme si hace lo que quiere.Con respecto al tema del ruido, el problema matemático es ubicar máximos / mínimos si queremos mirar el ruido podemos usar algo como convolve que se mencionó anteriormente.
fuente
Si bien esta pregunta es realmente antigua. Creo que hay un enfoque mucho más simple en numpy (una línea).
Para encontrar un máximo o mínimo local, esencialmente queremos encontrar cuándo la diferencia entre los valores de la lista (3-1, 9-3 ...) cambia de positivo a negativo (máximo) o de negativo a positivo (mínimo). Por tanto, primero encontramos la diferencia. Luego encontramos el signo, y luego encontramos los cambios de signo tomando la diferencia nuevamente. (Algo así como una primera y segunda derivada en cálculo, solo que tenemos datos discretos y no tenemos una función continua).
La salida en mi ejemplo no contiene los extremos (el primer y último valor de la lista). Además, al igual que el cálculo, si la segunda derivada es negativa, tienes un máximo, y si es positivo tienes un mínimo.
Así tenemos el siguiente emparejamiento:
fuente
Ninguna de estas soluciones funcionó para mí, ya que también quería encontrar picos en el centro de los valores repetidos. por ejemplo, en
ar = np.array([0,1,2,2,2,1,3,3,3,2,5,0])
la respuesta debería ser
Hice esto usando un bucle. Sé que no está súper limpio, pero hace el trabajo.
fuente
minm
ymaxm
contienen índices de mínimos y máximos, respectivamente. Para un conjunto de datos enorme, proporcionará muchos máximos / mínimos, por lo que en ese caso primero suavice la curva y luego aplique este algoritmo.fuente
Otra solución que utiliza esencialmente un operador dilatar:
y para los mínimos:
Además, desde
scipy.ndimage
puede reemplazarrank_filter(x, -1, size=3)
congrey_dilation
yrank_filter(x, 0, size=3)
congrey_erosion
. Esto no requerirá una clasificación local, por lo que es un poco más rápido.fuente
Otro:
fuente