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