熊猫寻找局部最大值和最小值

问题描述 投票:0回答:4

我有一个 pandas 数据框,有两列,一列是温度,另一列是时间。

我想将第三列和第四列称为最小值和最大值。这些列中的每一列都将填充 nan,除非有局部最小值或最大值,然后它将具有该极值。

这是数据的示例,本质上我试图识别图中的所有峰值和低点。

enter image description here

是否有任何带有 pandas 的内置工具可以完成此任务?

python pandas dataframe numpy time-series
4个回答
128
投票

fuglede提供的解决方案很棒,但如果你的数据非常嘈杂(如图所示),你最终会得到很多误导性的局部极值。我建议你使用

scipy.signal.argrelextrema()
方法。
.argrelextrema()
方法有其自身的局限性,但它有一个有用的功能,您可以指定要比较的点数,有点像噪声过滤算法。例如:

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()
               

几点:

  • 之后您可能需要检查这些点,以确保没有彼此非常接近的麻线点。
  • 你可以用
    n
    来过滤噪音点
  • argrelextrema
    返回一个元组,最后的
    [0]
    提取一个
    numpy
    数组

P.S.我开发了这种方法作为我的研究的一部分这里。如果您觉得有用,请随意引用我。


57
投票

假设感兴趣的列被标记为

data
,一种解决方案是

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)]

例如:

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()

enter image description here


6
投票

您可以执行类似于 Foad 的 .argrelextrema() 解决方案的操作,但使用 Pandas .rolling() 函数:

# Find local peaks
n = 5 #rolling period
local_min_vals = df.loc[df['data'] == df['data'].rolling(n, center=True).min()]
local_max_vals = df.loc[df['data'] == df['data'].rolling(n, center=True).max()]

plt.scatter(local_min_vals.index, local_min_vals, c='r')
plt.scatter(local_max_vals.index, local_max_vals, c='g')

Image of a noisy signal with red dots showing local minima and green dots showing local maxima.


3
投票

使用 Numpy

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

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

使用熊猫

ser = pd.Series(np.random.randint(2, 5, 100))
peak_df = ser[(ser.shift(1) < ser) & (ser.shift(-1) < ser)]
peak = peak_df.index
© www.soinside.com 2019 - 2024. All rights reserved.