我有一个Pandas Series
,其中包含加速时间序列数据。我的目标是在给定阈值的情况下选择极端力的切片。我能够通过以下方式获得支持:
extremes = series.where(lambda force: abs(force - RESTING_FORCE) >= THRESHOLD, other=np.nan)
现在extremes
包含超过阈值的所有值和任何不存在的值的NaN,维持原始索引。
然而,次要要求是附近的峰值应合并为单个事件。在视觉上,您可以想象左边的三个极端(两个高,一个低)连接到一个完整的段,右边的两个峰连接到另一个完整的段。
我已经阅读了整个Series
引用,但是我无法找到操作我的部分数据集的方法。例如,如果我有一个返回非NaN索引范围数组的方法,我将能够按顺序比较每个范围并决定是否用原始系列(附近)中的值填充空格或离开他们NaN(太远了)。
也许我需要放弃中间步骤并从一个完全不同的角度来解决这个问题?我是Python的新手,所以我很难在这方面做得很好。任何提示将不胜感激。
答案 0 :(得分:1)
在没有循环的情况下提出矢量化解决方案实际上并非如此简单。
您可能需要逐步完成代码以查看每种方法的实际结果,但这里只是简短的草图:
diff()
进行实际比较,以获得时间增量并应用时间增量比较以下是带有虚拟示例的代码:
%matplotlib inline
import pandas as pd
import numpy as np
size = 200
# create some dummy data
ts = pd.date_range(start="2017-10-28", freq="d", periods=size)
values = np.cumsum(np.random.normal(size=size)) + np.sin(np.linspace(0, 100, size))
series = pd.Series(values, index=ts, name="force")
series.plot(figsize=(10, 5))
# define thresholds
threshold_value = 6
threshold_time = pd.Timedelta(days=10)
# create data frame because we'll need helper columns
df = series.reset_index()
# get all initial peaks below or above threshold
mask = df["force"].abs().gt(threshold_value)
# create variable to store only timestamps of intial peaks
df.loc[mask, "ts_gap"] = df.loc[mask, "index"]
# create forward fill to enable comparison between current and next peak
df["ts_fill"] = df["ts_gap"].ffill()
# apply time delta comparison to filter only those within given time interval
df["within"] = df["ts_fill"].diff() < threshold_time
# convert boolean values into integers and
# create cummulative sum which creates group of consecutive timestamps
df["signals"] = (~df["within"]).astype(int).cumsum()
# create dataframe containing start and end values
df_signal = df.dropna(subset=["ts_gap"])\
.groupby("signals")["ts_gap"]\
.agg(["min", "max"])
# show results
df_signal
>>> min max
signals
10 2017-11-06 2017-11-27
11 2017-12-13 2018-01-22
12 2018-02-03 2018-02-23
最后,显示情节:
series.plot(figsize=(10, 5))
for _, (idx_min, idx_max) in df_signal.iterrows():
series[idx_min:idx_max].plot()
正如您在图中所看到的,如果它们的最后和第一个时间戳在10天的范围内,那么绝对值为6的峰值将合并为单个信号。这里的阈值是任意的,仅用于说明目的。你可以将它们变成任何东西。