Pandas 有效地从具有groupby和暂时条件的数据帧中删除行?

Pandas 有效地从具有groupby和暂时条件的数据帧中删除行?,pandas,dataframe,pandas-groupby,Pandas,Dataframe,Pandas Groupby,我有一个数千万行的数据帧: | userId | pageId | bannerId | timestap | |--------+--------+----------+---------------------| | A | P1 | B1 | 2020-10-10 01:00:00 | | A | P1 | B1 | 2020-10-10 01:00:10 | | B | P1 | B1

我有一个数千万行的数据帧:

| userId | pageId | bannerId | timestap            |
|--------+--------+----------+---------------------|
| A      | P1     | B1       | 2020-10-10 01:00:00 |
| A      | P1     | B1       | 2020-10-10 01:00:10 |
| B      | P1     | B1       | 2020-10-10 01:00:00 |
| B      | P2     | B2       | 2020-10-10 02:00:00 |
我要做的是删除所有行,其中对于相同的
userId,pageId,bannerId
,时间戳在相同的
userId,pageId,bannerId
对之前出现的
n
分钟内

我现在做的是:

# Get all instances of `userId, pageId, bannerId` that repeats,
# although, not all of them will have repeated within the `n` minute
# threshold I'm interested in.
groups = in df.groupby(['userId', 'pageId', 'bannerId']).userId.count()

# Iterate through each group, and manually check if the repetition was
# within `n` minutes. Keep track of all IDs to be removed.
to_remove = []
for user_id, page_id, banner_id in groups.index:
   sub = df.loc[
      (df.userId == user_id) &
      (df.pageId == pageId) &
      (df.bannerId == bannerId)
   ].sort_values('timestamp')

   # Now that each occurrence is listed chronologically,
   # check time diff.
   sub = sub.loc[
     ((sub.timestamp.shift(1) - sub.timestamp) / pd.Timedelta(minutes=1)).abs() <= n
   ]

   if sub.shape[0] > 0:
      to_remove += sub.index.tolist()
#获取所有重复出现的“userId、pageId、bannerId”实例,
#不过,并不是所有这些都会在一分钟内重复
#我感兴趣的门槛。
groups=在df.groupby(['userId','pageId','bannerId']).userId.count()中
#迭代每个组,并手动检查重复是否正确
#几分钟之内。跟踪所有要删除的ID。
删除=[]
对于组中的用户标识、页面标识、横幅标识。索引:
sub=df.loc[
(df.userId==user\u id)&
(df.pageId==pageId)&
(df.bannerId==bannerId)
].sort_值(“时间戳”)
#现在,每个事件都按时间顺序列出,
#检查时间差。
sub=sub.loc[
((sub.timestamp.shift(1)-sub.timestamp)/pd.Timedelta(分钟=1)).abs()0:
to_remove+=sub.index.tolist()

这确实是我想要的。唯一的问题是,由于我拥有大量的数据,完成它需要几个小时。

为了得到更具指导性的结果,我花了更长的时间 源数据帧:

  userId pageId bannerId            timestap
0      A     P1       B1 2020-10-10 01:00:00
1      A     P1       B1 2020-10-10 01:04:10
2      A     P1       B1 2020-10-10 01:05:00
3      A     P1       B1 2020-10-10 01:08:20
4      A     P1       B1 2020-10-10 01:09:30
5      A     P1       B1 2020-10-10 01:11:00
6      B     P1       B1 2020-10-10 01:00:00
7      B     P2       B2 2020-10-10 02:00:00
注意:timestap列是datetime类型

从为组定义“筛选”功能开始 timestap值(对于某些用户ID组合, pageId和bannerId):

然后设置时间阈值(分钟数):

最后一件事是生成结果:

result = df.groupby(['userId', 'pageId', 'bannerId'])\
    .timestap.apply(myFilter, nMin).explode().reset_index()
对于我的数据样本,结果是:

  userId pageId bannerId            timestap
0      A     P1       B1 2020-10-10 01:00:00
1      A     P1       B1 2020-10-10 01:05:00
2      A     P1       B1 2020-10-10 01:11:00
3      B     P1       B1 2020-10-10 01:00:00
4      B     P2       B2 2020-10-10 02:00:00
请注意,“普通”差异是不够的,因为例如,从 时间戳为01:05:00的行,以下两行(01:08:20和01:09:30) 应放弃,因为它们在01:05:00起的5分钟限制内

因此,仅查看前一行是不够的。 从某一行开始,您应该“标记为删除”以下所有行,直到 您会发现一行的时间戳与 “开始行”超出限制。 在本例中,仅此行成为分析的起始行
下面的行(在当前组中)。

使用
df.groupby(['userId','pageId','bannerId'])['timestamp'].diff()
非常感谢。这是一个简单的解决方案。回答得很好。非常感谢。我相信我已经使用
by_time=df.sort_值('timestamp')。groupby(['userId','pageId','bannerId'))。timestamp.diff()实现了它/pd.Timedelta(minutes=1);by_-time.loc[by_-time
。我用几个用例对它进行了测试,所以它似乎可以完成任务。
result = df.groupby(['userId', 'pageId', 'bannerId'])\
    .timestap.apply(myFilter, nMin).explode().reset_index()
  userId pageId bannerId            timestap
0      A     P1       B1 2020-10-10 01:00:00
1      A     P1       B1 2020-10-10 01:05:00
2      A     P1       B1 2020-10-10 01:11:00
3      B     P1       B1 2020-10-10 01:00:00
4      B     P2       B2 2020-10-10 02:00:00