识别 pandas 时间序列中的极值
Identifying extremes in pandas timeseries
我正在寻找一种方法来识别 pandas 时间序列中的局部极值。
MWE 将是
import math
import matplotlib.pyplot as plt
import pandas as pd
sin_list = []
for i in range(200):
sin_list.append(math.sin(i / 10) + i / 100)
idx = pd.date_range('2018-01-01', periods=200, freq='H')
ts = pd.Series(sin_list, index=idx)
ts.plot(style='.')
plt.show()
并且红线将标记我想要识别的时间戳。请注意,当然,这个系列中有有限的步骤。
一个可能的解决方案是用一条曲线拟合它,导出它,然后确定梯度为 0 的确切位置。这似乎是我自己编程的一个很大的努力,我假设这样的实现存在于某处.
我基于.diff()
模块开发了一个解决问题的方法。这里的关键属性是 get_percentile 函数的 p
因子。由于有限数量的值意味着梯度不会达到值 0,因此解决方案 space 必须有点模糊。这意味着,值越少,p
因子就必须越高。在我的解决方案中,0.05 被证明足以识别极值,但小到足以以合理的精度定位极值。
这是代码:
import copy
import math
import matplotlib.pyplot as plt
import pandas as pd
def get_percentile(data: list, p: float):
_data = copy.copy(data)
_data.sort()
result = _data[math.floor(len(_data) * p) - 1]
return result
sin_list = []
for i in range(200):
sin_list.append(math.sin(i / 10) + i / 100)
idx = pd.date_range('2018-01-01', periods=200, freq='H')
ts = pd.Series(sin_list, index=idx)
gradient_ts = abs(ts.diff())
percentile = get_percentile(gradient_ts.values, p=0.05)
binary_ts = gradient_ts.where(gradient_ts > percentile, 1).where(gradient_ts < percentile, 0)
fig, ax = plt.subplots()
binary_ts.plot(drawstyle="steps", ax=ax)
ax.fill_between(binary_ts.index, binary_ts, facecolor='green', alpha=0.5, step='pre')
ts.plot(secondary_y=True, style='.')
plt.show()
我正在寻找一种方法来识别 pandas 时间序列中的局部极值。
MWE 将是
import math
import matplotlib.pyplot as plt
import pandas as pd
sin_list = []
for i in range(200):
sin_list.append(math.sin(i / 10) + i / 100)
idx = pd.date_range('2018-01-01', periods=200, freq='H')
ts = pd.Series(sin_list, index=idx)
ts.plot(style='.')
plt.show()
并且红线将标记我想要识别的时间戳。请注意,当然,这个系列中有有限的步骤。
一个可能的解决方案是用一条曲线拟合它,导出它,然后确定梯度为 0 的确切位置。这似乎是我自己编程的一个很大的努力,我假设这样的实现存在于某处.
我基于.diff()
模块开发了一个解决问题的方法。这里的关键属性是 get_percentile 函数的 p
因子。由于有限数量的值意味着梯度不会达到值 0,因此解决方案 space 必须有点模糊。这意味着,值越少,p
因子就必须越高。在我的解决方案中,0.05 被证明足以识别极值,但小到足以以合理的精度定位极值。
这是代码:
import copy
import math
import matplotlib.pyplot as plt
import pandas as pd
def get_percentile(data: list, p: float):
_data = copy.copy(data)
_data.sort()
result = _data[math.floor(len(_data) * p) - 1]
return result
sin_list = []
for i in range(200):
sin_list.append(math.sin(i / 10) + i / 100)
idx = pd.date_range('2018-01-01', periods=200, freq='H')
ts = pd.Series(sin_list, index=idx)
gradient_ts = abs(ts.diff())
percentile = get_percentile(gradient_ts.values, p=0.05)
binary_ts = gradient_ts.where(gradient_ts > percentile, 1).where(gradient_ts < percentile, 0)
fig, ax = plt.subplots()
binary_ts.plot(drawstyle="steps", ax=ax)
ax.fill_between(binary_ts.index, binary_ts, facecolor='green', alpha=0.5, step='pre')
ts.plot(secondary_y=True, style='.')
plt.show()