gpt4 book ai didi

python - 根据索引和值条件选择 Pandas 系列的切片

转载 作者:行者123 更新时间:2023-12-01 02:30:01 25 4
gpt4 key购买 nike

我有一个 Pandas Series,其中包含加速时间序列数据。我的目标是在给定阈值的情况下选择极端力量的切片。我能够完成以下工作:

extremes = series.where(lambda force: abs(force - RESTING_FORCE) >= THRESHOLD, other=np.nan) 

现在,extremes 包含超过阈值的所有值,对于任何未超过阈值的值,则包含 NaN,从而保持原始索引。

enter image description here

但是,第二个要求是附近的峰值应合并为单个事件。从视觉上看,您可以想象左侧的三个极端(两个高,一个低)连接成一个完整的线段,而右侧的两个峰连接成另一个完整的线段。

我已通读整个 Series 引用资料,但我无法找到对部分数据集进行操作的方法。例如,如果我有一个返回非 NaN 索引范围数组的方法,我将能够按顺序比较每个范围并决定是否用原始系列(附近)中的值填充之间的空间或离开它们为 NaN(相距太远)。

也许我需要放弃中间步骤并从完全不同的角度来解决这个问题?我是 Python 新手,所以在这方面我很难走得更远。任何提示将不胜感激。

最佳答案

实际上,想出一个没有循环的矢量化解决方案并不是那么简单。

您可能需要逐步浏览代码才能看到每种方法的实际结果,但这里是这个想法的简短概述:

解决方案概述

  1. 通过简单的阈值过滤器识别所有峰值
  2. 将峰值时间戳获取到列中,并向前填充之间的间隙,以便将当前有效时间戳与之前的有效时间戳进行比较
  3. 通过 diff() 进行实际比较以获取时间增量并应用时间增量比较
  4. 将 bool 值转换为整数,以使用累积和创建信号组
  5. 按信号分组并获取最小和最大时间戳值

示例数据

这是带有虚拟示例的代码:

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

enter image description here

解决方案代码

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

enter image description here

结果

正如您在图中看到的,如果最后一个和第一个时间戳在 10 天的范围内,则绝对值大于 6 的峰值将合并为单个信号。这里的阈值是任意的,仅用于说明目的。您可以将它们更改为任何内容。

关于python - 根据索引和值条件选择 Pandas 系列的切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46939588/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com