【问题标题】:Efficiency: Check if value in Pandas DataFrame has changed with an specific threshold outside an interval of measurement效率:检查 Pandas DataFrame 中的值是否在测量间隔之外随特定阈值发生变化
【发布时间】:2019-11-29 08:16:05
【问题描述】:

我有一个传感器记录的列。
此数据上有一些噪音,因此在未检测到任何内容时,每个时间点的值并不完全相同。
我想将该记录的 DataFrame 拆分为仅包含“有趣”数据的新 DataFrame(其值大于列“B”的某个阈值,在本示例中大于 5)。
在此示例中,“A”表示时间戳,“B”表示传感器数据,带有噪声。
此示例的预期结果是两个 DataFrame。一个包含 5 到 6 行,另一个包含 10 到 15 行。

DataFrame 上的正常循环非常耗时,因为 DataFrame 有大约 24mio 行。有没有一种有效的方法来处理 pandas 或类似问题中的此类问题?

例子:


# |  A  |  B  
--+-----+-----
1 |  1  |  0.10
2 |  2  |  0.11
3 |  3  |  0.09
4 |  4  |  0.12
5 |  5  |  5.24
6 |  6  |  6.33
7 |  7  |  0.08
8 |  8  |  0.09
9 |  9  |  0.10
10|  10 |  7.54
11|  11 |  8.33
12|  12 |  9.03
13|  13 |  1.43
14|  14 |  9.64
15|  15 |  9.03
16|  16 |  0.43
17|  17 |  0.53
18|  18 |  0.62
19|  19 |  0.73
20|  20 |  0.51

在“有趣的区间”之间可能会出现低于阈值的值。结束间隔的指示是连续 1000 个值低于阈值。

谢谢!

【问题讨论】:

  • 我想要在我的测量过程中每次发生“动作”时使用单独的数据帧。所以基本上传感器被激活了......几分钟后(数千行),第一个动作发生了大约 1 分钟。在那个“动作”期间,“B”的值可以得到任何值。动作结束后,又是几分钟的休息时间。比下一个动作发生约 1 分钟,比中断、动作、中断等。我想要每个动作的单独数据框。以下答案的问题是,阈值还会过滤掉低于阈值的值
  • 困难的部分是在第 13 行你的值低于 5。所以按照你的逻辑,它看起来像是在关闭和打开。那么是否也可以假设 < 1 已关闭,这样第 13 行将被标记为已打开。

标签: python pandas dataframe


【解决方案1】:

这是一个通用的解决方案,并试图捕捉边缘情况:

# all rows where B > 5
mask1 = df['B'].gt(5)

# all rows where Bt-1 > 5 & Bt+1 > 5
mask2 = df['B'].shift().gt(5) & df['B'].shift(-1).gt(5)

# all rows where mask1 OR mask2 is True
mask3 = (mask1 | mask2)

# turn rows where mask 3 is False to NaN
mask4 = mask3.astype(int).diff().eq(1).cumsum().where(mask3)

# put each group of turned on sensor into a different dataframe
dfs = [dfg.reset_index(drop=True) for _, dfg in df.groupby(mask4)]

输出

for d in dfs:
    print(d, '\n')

   A    B
4  5 5.24
5  6 6.33 

     A    B
9   10 7.54
10  11 8.33
11  12 9.03
12  13 1.43
13  14 9.64
14  15 9.03 

或者在函数中:

def split_turn_on_off(dataframe):
    mask1 = dataframe['B'].gt(5)
    mask2 = dataframe['B'].shift().gt(5) & dataframe['B'].shift(-1).gt(5)
    mask3 = (mask1 | mask2)
    mask4 = mask3.astype(int).diff().eq(1).cumsum().where(mask3)

    # put each group of turned on sensor into a different dataframe
    dataframes = [dataframeg.reset_index(drop=True) for _, dataframeg in dataframe.groupby(mask4)]

    return dataframes

【讨论】:

  • 非常好的解决方案。我还为熊猫学习了新的鼓舞人心的功能!非常感谢!
猜你喜欢
  • 1970-01-01
  • 2020-09-07
  • 2022-11-22
  • 2020-03-09
  • 1970-01-01
  • 2018-06-08
  • 2018-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多