【问题标题】:Find timestamps in pandas dataframe that are at least 30 minutes apart but not at regular 30 minute intervals在 pandas 数据帧中查找至少相隔 30 分钟但不是定期 30 分钟间隔的时间戳
【发布时间】:2021-07-06 17:56:40
【问题描述】:

我正在寻找一种更快/更聪明的方法来做我目前正在做的事情。

我有一个 pandas 数据框,其中包含两列感兴趣的“日期时间”和“值”。我想找到 Value 超过某个阈值但有 30 分钟窗口的所有行。 30 分钟窗口从第一次值 > 阈值开始(在一个分组中)。

假设阈值 = 0.5,我们有以下行。

DateTime,Value
2021-07-06 09:00:00,0.4
2021-07-06 09:01:00,0.51
2021-07-06 09:02:00,0.55
2021-07-06 09:03:00,0.56
2021-07-06 09:04:00,0.49
2021-07-06 09:05:00,0.51
2021-07-06 09:29:00,0.2
2021-07-06 09:30:00,0.6
2021-07-06 09:31:00,0.1
2021-07-06 09:45:00,0.7
2021-07-06 09:46:00,0.8

所以在这种情况下,要返回的第一行是 9:01,接下来是 9:45。

目前,我通过迭代找到这些行,效率非常低。有没有更好的方法更矢量化?我有数百个这样的文件,数百万行,许多阈值,并且需要几个小时才能完成。

import pandas as pd
row_indices = []
threshold_val = 0.5
wait_time = pd.Timedelta(30, unit='m')
df = pd.read_csv('sample_data.csv')
df['DateTime'] = pd.to_datetime(df['DateTime'], format='%Y-%m-%d %H:%M:%S')
rows = df[df['Value'] > threshold_val] 
while len(rows) > 0:
    row_index = rows.first_valid_index()
    row_time = rows['DateTime'][row_index]
    row_indices.append(row_index)
    rows = rows[rows['DateTime'] > row_time + wait_time]

结果:

df
Out[112]: 
              DateTime  Value
0  2021-07-06 09:00:00   0.40
1  2021-07-06 09:01:00   0.51
2  2021-07-06 09:02:00   0.55
3  2021-07-06 09:03:00   0.56
4  2021-07-06 09:04:00   0.49
5  2021-07-06 09:05:00   0.51
6  2021-07-06 09:29:00   0.20
7  2021-07-06 09:30:00   0.60
8  2021-07-06 09:31:00   0.10
9  2021-07-06 09:45:00   0.70
10 2021-07-06 09:46:00   0.80

row_indices
Out[113]: [1, 9]

【问题讨论】:

    标签: python pandas dataframe datetime


    【解决方案1】:

    希望我正确理解了您的问题:

    df = df.loc[df.Value > 0.5]
    df = df.reset_index()
    df["DateTime2"] = df["DateTime"]
    
    print(
        df.groupby(pd.Grouper(freq="30min", key="DateTime", origin="start"))
        .first()
        .reset_index(drop=True)
    )
    

    打印:

       index  Value           DateTime2
    0      1   0.51 2021-07-06 09:01:00
    1      9   0.70 2021-07-06 09:45:00
    

    索引位于index 列中:19

    【讨论】:

      【解决方案2】:

      让我们从找出所有高于阈值的值开始:

      df2 = df[df.Value > 0.5]
      

      然后,按 30min 分组(+1s 为独占)并保留每组的第一个值:

      df2['DateTime'] = pd.to_datetime(df2['DateTime']) ## make sure DateTime is DateTime type
      d.reset_index().groupby(pd.Grouper(freq='30min1s', key='DateTime')).index.first().values
      

      输出:

      [1,9]
      

      让我们知道它的运行速度!

      【讨论】:

      • freq='30min', closed='right' 选项也可以
      • 这和上面的答案非常接近,但并不完全正确。我很难获得真正的排他性。我的原始方法将正确地将 14:40:50 和 15:11:00 识别为 30 分钟独占窗口。但是,pd.Grouper 标识 14:40:50 和 15:10:50。这是使用 freq='30min1s' 或 '30min10s' 或 '1801s' 或 '1810s' 的许多变体。 closed='right' 似乎会引发一些奇怪的行为,选择 13:36:50 和 13:27:00。参考我上面使用的rowsdf.iloc[rows.reset_index().groupby(pd.Grouper(freq='1801s', key='DateTime', origin='start')).first()['index'].values]
      • 你能举一个它不能按预期工作的示例数据集吗?
      猜你喜欢
      • 2021-07-16
      • 2019-09-28
      • 2019-04-12
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-12
      相关资源
      最近更新 更多