【问题标题】:Pandas finding local max and min熊猫找到局部最大值和最小值
【发布时间】:2018-06-09 23:25:16
【问题描述】:

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

我想创建第三列和第四列,分别称为 min 和 max。这些列中的每一列都将用 nan 填充,除非存在局部最小值或最大值,否则它将具有该极值的值。

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

是否有任何带有 pandas 的内置工具可以做到这一点?

【问题讨论】:

  • 结果是否应该对噪声具有鲁棒性?否则,您可以将 Series 的值与其班次进行比较。
  • 在这种情况下我不担心噪音,如果是噪音信号我会过滤然后在过滤结果中寻找最大/最小
  • 您也可以将一个非常简单的模型(例如具有一个或两个协变量的线性模型)拟合到数据中,然后从残差项中保留那些偏差在q% 最小或最大类别中的模型,使用pd.quantile

标签: python pandas dataframe numpy time-series


【解决方案1】:

The solution offered by 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 数组

【讨论】:

【解决方案2】:

假设感兴趣的列标记为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()

【讨论】:

  • 我发现当数据的值重复时,例如多行值为 7,仅使用 会错过作为“最小值”或“最大值”的数据点。将此解决方案修改为具有 ".shift(1) =" 实际上确实允许识别重复值的 'min' 和 'max' 值。逻辑是包含重复值的最后一行将被视为'min'或'max'。
  • 伟大的发现 Udesh
【解决方案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

【讨论】:

    猜你喜欢
    • 2021-03-28
    • 2021-01-13
    • 2023-01-05
    • 2020-04-28
    • 2021-09-12
    相关资源
    最近更新 更多