Saltar al contenido

Pandas encontrando máximos y mínimos locales

Esta es la contestación más correcta que te podemos aportar, pero mírala pausadamente y valora si se puede adaptar a tu proyecto.

Solución:

La solución que ofrece fuglede es excelente, pero si sus datos son muy ruidosos (como el de la imagen), terminará con muchos extremos locales engañosos. Te sugiero que uses scipy.signal.argrelextrema() método. los .argrelextrema() El método tiene sus propias limitaciones, pero tiene una característica útil en la que puede especificar el número de puntos que se compararán, algo así como un algoritmo de filtrado de ruido. por ejemplo:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.signal import argrelextrema

# Generate a noisy AR(1) sample

np.random.seed(0)
rs = np.random.randn(200)
xs = [0]
for r in rs:
    xs.append(xs[-1] * 0.9 + r)
df = pd.DataFrame(xs, columns=['data'])

n = 5  # number of points to be checked before and after

# Find local peaks

df['min'] = df.iloc[argrelextrema(df.data.values, np.less_equal,
                    order=n)[0]]['data']
df['max'] = df.iloc[argrelextrema(df.data.values, np.greater_equal,
                    order=n)[0]]['data']

# Plot results

plt.scatter(df.index, df['min'], c='r')
plt.scatter(df.index, df['max'], c='g')
plt.plot(df.index, df['data'])
plt.show()

Algunos puntos:

  • es posible que deba verificar los puntos después para asegurarse de que no haya puntos de hilo muy cerca uno del otro.
  • puedes jugar con n para filtrar los puntos ruidosos
  • argrelextrema devuelve una tupla y la [0] al final extrae un numpy array

Suponiendo que la columna de interés está etiquetada datauna solución sería

df['min'] = df.data[(df.data.shift(1) > df.data) & (df.data.shift(-1) > df.data)]
df['max'] = df.data[(df.data.shift(1) < df.data) & (df.data.shift(-1) < df.data)]

Por ejemplo:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Generate a noisy AR(1) sample
np.random.seed(0)
rs = np.random.randn(200)
xs = [0]
for r in rs:
    xs.append(xs[-1]*0.9 + r)
df = pd.DataFrame(xs, columns=['data'])

# Find local peaks
df['min'] = df.data[(df.data.shift(1) > df.data) & (df.data.shift(-1) > df.data)]
df['max'] = df.data[(df.data.shift(1) < df.data) & (df.data.shift(-1) < df.data)]

# Plot results
plt.scatter(df.index, df['min'], c='r')
plt.scatter(df.index, df['max'], c='g')
df.data.plot()

ingrese la descripción de la imagen aquí

usando numpy

ser = np.random.randint(-40, 40, 100) # 100 points
peak = np.where(np.diff(ser) < 0)[0]

o

double_difference = np.diff(np.sign(np.diff(ser)))
peak = np.where(double_difference == -2)[0]

usando pandas

ser = pd.Series(np.random.randint(2, 5, 100))
peak_df = ser[(ser.shift(1) < ser) & (ser.shift(-1) < ser)]
peak = peak_df.index

Calificaciones y reseñas

Si conservas algún reparo y disposición de reaccionar nuestro escrito puedes añadir una nota y con deseo lo observaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *