[英]How to find all local maxima and minima in a Python Pandas series without knowing the frequency of the window
作為我問題的背景,請允許我解釋我要解決的問題。 我有一個傳感器正在收集壓力數據。 我將這些數據收集到 pandas dataframe 中,結構如下:
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 plot dataframe 並直觀地查看為系統供電的壓縮機何時運行、多久運行一次以及對系統加壓需要多長時間。 Plot的壓力數據:
從圖中可以明顯看出,plot 左側的周期比右側的周期短得多。
我要解決的問題是我想以編程方式計算最后一個完整開關周期的最大壓力、最小壓力、周期長度和占空比。 一個好處是以編程方式計算 24 小時期間的總運行時間。
我想我需要對壓力序列求導,並且我正在使用在python pandas: how to calculate derived/gradient找到的解決方案。
然后,當壓縮機運行(正數)而不是(零或負數)時,導數系列將以數字形式顯示。 我在想,然后我可以找到各個峰的所有最大值和最小值,並從那里得到它們之間的時間增量。
However, the problem I'm running into is any solutions I've found so far require me to know in advance how large a window to use (for example, the order argument when using SciPy argrelextrema https://docs.scipy.org /doc/scipy/reference/generated/scipy.signal.argrelextrema.html )。
但是我的數據系列的周期短至幾分鍾,理想情況下(如果我們沒有泄漏。)周期應該延長到幾小時或更長時間,使用短 windows 會導致我在較長的周期中出現錯誤的最大值和最小值。 更長的 windows 會導致我錯過較短的許多最大值和最小值。
以編程方式查看上述 plot 中顯而易見的內容的任何想法?
Mr.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()
cycle_times 樣本:
>>> 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
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.