【问题标题】:Efficient way of filtering by datetime in groupbygroupby中按日期时间过滤的有效方法
【发布时间】:2023-03-16 01:30:02
【问题描述】:

鉴于DataFrame由以下生成:

import numpy as np
import pandas as pd
from datetime import timedelta

np.random.seed(0)
rng = pd.date_range('2015-02-24', periods=14, freq='9H')
ids = [1]*5 + [2]*2 + [3]*7
df = pd.DataFrame({'id': ids, 'time_entered': rng, 'val': np.random.randn(len(rng))})

df:

    id  time_entered        val
0   1   2015-02-24 00:00:00 1.764052
1   1   2015-02-24 09:00:00 0.400157
2   1   2015-02-24 18:00:00 0.978738
3   1   2015-02-25 03:00:00 2.240893
4   1   2015-02-25 12:00:00 1.867558
5   2   2015-02-25 21:00:00 -0.977278
6   2   2015-02-26 06:00:00 0.950088
7   3   2015-02-26 15:00:00 -0.151357
8   3   2015-02-27 00:00:00 -0.103219
9   3   2015-02-27 09:00:00 0.410599
10  3   2015-02-27 18:00:00 0.144044
11  3   2015-02-28 03:00:00 1.454274
12  3   2015-02-28 12:00:00 0.761038
13  3   2015-02-28 21:00:00 0.121675

对于每个 id,我需要从最新的 time_entered 中删除超过 24 小时(1 天)的行,对于该 id。我目前的解决方案:

def custom_transform(x):
    datetime_from = x["time_entered"].max() - timedelta(days=1)
    x = x[x["time_entered"] > datetime_from]
    return x

df.groupby("id").apply(lambda x: custom_transform(x)).reset_index(drop=True)

给出正确的、预期的输出:

    id  time_entered        val
0   1   2015-02-24 18:00:00 0.978738
1   1   2015-02-25 03:00:00 2.240893
2   1   2015-02-25 12:00:00 1.867558
3   2   2015-02-25 21:00:00 -0.977278
4   2   2015-02-26 06:00:00 0.950088
5   3   2015-02-28 03:00:00 1.454274
6   3   2015-02-28 12:00:00 0.761038
7   3   2015-02-28 21:00:00 0.121675

但是,我的真实数据是几千万行,几十万个唯一id,正因为如此,这个解决方案是不可行的(需要很长时间)。

有没有更有效的方法来过滤数据?我感谢所有想法!

【问题讨论】:

    标签: python pandas numpy optimization pandas-groupby


    【解决方案1】:

    一般情况下,请避免使用 groupby().apply(),因为它不是跨组向量化的,更不用说在您的情况下返回新数据帧时的内存分配开销。

    如何使用groupby().transform 找到时间阈值,然后对整个数据使用布尔索引:

    time_max_by_id = df.groupby('id')['time_entered'].transform('max') - pd.Timedelta('1D')
    df[df['time_entered'] > time_max_by_id]
    

    输出:

        id        time_entered       val
    2    1 2015-02-24 18:00:00  0.978738
    3    1 2015-02-25 03:00:00  2.240893
    4    1 2015-02-25 12:00:00  1.867558
    5    2 2015-02-25 21:00:00 -0.977278
    6    2 2015-02-26 06:00:00  0.950088
    11   3 2015-02-28 03:00:00  1.454274
    12   3 2015-02-28 12:00:00  0.761038
    13   3 2015-02-28 21:00:00  0.121675
    

    【讨论】:

      【解决方案2】:
      df.groupby('id').apply(lambda x : x[(x['time_entered'].max()-x['time_entered'])<pd.Timedelta('1D')]).reset_index(drop=True)
      Out[322]: 
         id        time_entered       val
      0   1 2015-02-24 18:00:00  0.978738
      1   1 2015-02-25 03:00:00  2.240893
      2   1 2015-02-25 12:00:00  1.867558
      3   2 2015-02-25 21:00:00 -0.977278
      4   2 2015-02-26 06:00:00  0.950088
      5   3 2015-02-28 03:00:00  1.454274
      6   3 2015-02-28 12:00:00  0.761038
      7   3 2015-02-28 21:00:00  0.121675
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-04
        • 2013-10-20
        • 1970-01-01
        • 2020-09-25
        • 2021-09-01
        • 2021-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多