如何在不知道窗口频率的情况下查找Python系列中的所有局部最大值和最小值

2024-10-01 19:34:39 发布

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

作为我问题的背景,请允许我解释一下我试图解决的问题。我有一个传感器正在收集压力数据。我正在将这些数据收集到熊猫数据框中,结构如下:

DateTime                             Transmission Line PSI                
2021-02-18 11:55:34                  3.760
2021-02-18 11:55:49                  3.359
2021-02-18 11:56:04                  3.142
2021-02-18 11:56:19                  3.009
2021-02-18 11:56:34                  2.938
...                                    ...
2021-02-19 12:05:06                  3.013
2021-02-19 12:05:21                  3.011
2021-02-19 12:05:36                  3.009
2021-02-19 12:05:51                  3.009
2021-02-19 12:06:06                  3.007

我可以用pyplot绘制数据帧,直观地看到供给系统的压缩机何时运行,多久运行一次,以及系统加压需要多长时间。压力数据曲线图:
enter image description here

从图中可以明显看出,绘图左侧的周期比右侧的周期短得多

我试图解决的问题是,我想通过编程计算上一个完整的开关循环的最大压力、最小压力、周期长度和占空比。另外一个好处是以编程方式计算24小时内的总运行时间

我想我需要取压强级数的导数,我使用在python pandas: how to calculate derivative/gradient找到的解

衍生系列的绘图:
enter image description here

然后,当压缩机运行时,导数序列将以数字形式显示(正数),而不是(零数或负数)。我在想,我可以找到各个峰值的所有最大值和最小值,并从中得到它们之间的时间差

然而,我遇到的问题是,到目前为止,我发现的任何解决方案都要求我提前知道要使用多大的窗口(例如,使用SciPy argrelextremahttps://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.argrelextrema.html时的order参数)

但我的数据系列的特点是周期短至几分钟,理想情况下(如果我们没有泄漏!)周期应延长至数小时或更长。使用短窗口会使我在较长的周期中出现错误的最大值和最小值,而较长的窗口会使我在较短的周期中错过许多最大值和最小值

在上面的情节中,你有什么想法可以通过编程的方式看到什么是显而易见的


Tags: 数据绘图datetime系统编程方式传感器scipy
1条回答
网友
1楼 · 发布于 2024-10-01 19:34:39

上面T先生的评论有我的答案。。。使用scipy.signal.find_peaks可以让我做我需要的事情。在下面发布代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
import scipy.signal as sig

namespace = ['DateTime', 'Transmission Line PSI']
    
plt.rcParams["figure.figsize"] = [16.0, 9.0]
fig, ax = plt.subplots()
df = pd.read_csv(r'\\192.168.1.1\raid\graphdata.csv', names=namespace)

# convert imported date/time information to real datetimes and set as index
df['DateTime'] = pd.to_datetime(df['DateTime'])
df = df.set_index(df['DateTime']).drop('DateTime', axis=1)

# take first derivative of pressure data to show when pressure is rising or falling
df['deltas'] = df['Transmission Line PSI'].diff() / df.index.to_series().diff().dt.total_seconds()
df['deltas'] = df['deltas'].fillna(0)

peaks, _ = sig.find_peaks(df['deltas'], height=0.01)
neg_peaks, _ = sig.find_peaks(-df['deltas'], height=0.01)

# plotting peaks and neg_peaks against first derivative
plt.scatter(df.iloc[peaks].index, df.iloc[peaks]['deltas'])
plt.scatter(df.iloc[neg_peaks].index, df.iloc[neg_peaks]['deltas'])
plt.plot(df['deltas'])
plt.show()

# find timedeltas between all positive peaks - these are the periods of the cycle times
cycle_times = df.iloc[peaks].index.to_series().diff().dt.seconds.div(60, fill_value=0)

# plot periods
plt.plot(cycle_times)
plt.show()

根据一阶导数得出的峰值曲线图: plot of peaks against first derivative

循环时间示例:

>>> cycle_times
DateTime
2021-02-18 11:59:04     0.000000
2021-02-18 12:04:04     5.000000
2021-02-18 12:09:35     5.516667
2021-02-18 12:16:05     6.500000
2021-02-18 12:21:35     5.500000
                         ...    
2021-02-19 08:54:09    17.016667
2021-02-19 09:27:56    33.783333
2021-02-19 10:15:44    47.800000
2021-02-19 11:24:19    68.583333
2021-02-19 12:02:36    38.283333
Name: DateTime, Length: 267, dtype: float64

循环时间曲线图: Plot of cycle times

https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html

相关问题 更多 >

    热门问题