Pandas找到本地最大值和最小值

2024-09-21 00:57:25 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我想把第三列和第四列称为min和max。这些列中的每一列都用nan填充,除非有一个局部的min或max,那么它的值就是极值。

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

enter image description here

有没有内置的熊猫工具可以做到这一点?


Tags: 工具数据时间局部nanmin温度内置
3条回答

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

enter image description here

一些要点:

  • 你可能需要检查之后的点,以确保没有点非常接近对方。
  • 你可以用n来过滤噪声点
  • argrelextrema返回元组,末尾的[0]提取numpy数组

使用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

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

相关问题 更多 >

    热门问题