如何在GroupBy中“折叠”符合逻辑条件的行

2024-09-30 18:16:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样一个数据帧:

In [134]: df
Out[134]: 
            A                               ID3            DATETIME
0  BRT-481028  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 13:43:27
1  BRT-481054  4a57ed0b02fa357bf3c51cc9460e8d96 2014-10-08 14:26:19
2  BRT-481076  1a682034f8cbc542f36e46215635da9a 2014-10-08 14:29:01
3  BRT-481023  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:39:34
4  BRT-481023  f88g8d7sds799asde83b2523944p9r78 2014-10-08 18:40:18
5  BRT-481033  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:44:30
6  BRT-481032  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:46:00
7  BRT-481037  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:52:15
8  BRT-481046  db959faf023e5df33032db4808882f0c 2014-10-08 18:59:59
9  BRT-481053  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 19:17:48
10 BRT-481065  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 19:21:38

每一行表示由用户触发的事件——为了本例,通过df['ID3']中的值标识。每个事件都有很多附加属性,但我已经删掉了其他所有属性

对于我尝试构建的内容,我只需要为每个用户和每5分钟滚动周期保留一个事件。在同一时间段内,由同一个用户执行的所有其他事件都只是干扰其他逻辑的噪声,这些逻辑将进一步执行,因此应该被丢弃。因此,我需要为每个用户保留最多一条记录,滚动周期为5分钟。更具体地说,我需要保持最新的记录在任何数量的记录在同一时间段

所需的输出如下所示:

            A                               ID3            DATETIME
0  BRT-481028  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 13:43:27
1  BRT-481054  4a57ed0b02fa357bf3c51cc9460e8d96 2014-10-08 14:26:19
2  BRT-481076  1a682034f8cbc542f36e46215635da9a 2014-10-08 14:29:01
4  BRT-481023  f88g8d7sds799asde83b2523944p9r78 2014-10-08 18:40:18
6  BRT-481032  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:46:00
7  BRT-481037  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:52:15
8  BRT-481046  db959faf023e5df33032db4808882f0c 2014-10-08 18:59:59
10 BRT-481065  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 19:21:38

上面第[3,5,9]行上的记录已被丢弃,因为它们满足上述条件。另外,请注意行36之间的时间间隔是如何大于5分钟的,但是,由于同时创建了记录5,因此滚动窗口使得这些记录被丢弃

还要注意,行4上的记录保持不变,因为它与不同的用户相关联

编辑

现在我更进一步了,我用diff()groupby()来理解这一点:

In [309]: df['diff'] = df.sort_values(by='DATETIME').groupby('ID3')['DATETIME'].transform(lambda x: x.diff())

In [310]: df
Out[310]: 
             A                               ID3            DATETIME  \
0   BRT-481028  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 13:43:27   
1   BRT-481054  4a57ed0b02fa357bf3c51cc9460e8d96 2014-10-08 14:26:19   
2   BRT-481076  1a682034f8cbc542f36e46215635da9a 2014-10-08 14:29:01   
3   BRT-481023  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:39:34   
4   BRT-481023  f88g8d7sds799asde83b2523944p9r78 2014-10-08 18:40:18   
5   BRT-481033  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:44:30   
6   BRT-481032  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:46:00   
7   BRT-481037  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 18:52:15   
8   BRT-481046  db959faf023e5df33032db4808882f0c 2014-10-08 18:59:59   
9   BRT-481053  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 19:17:48   
10  BRT-481065  b76cd912ffcb97e21de83b252391b2a0 2014-10-08 19:21:38   

                  diff  
0                  NaT  
1                  NaT  
2                  NaT  
3  1970-01-01 04:56:07  
4                  NaT  
5  1970-01-01 00:04:56  
6  1970-01-01 00:01:30  
7  1970-01-01 00:06:15  
8                  NaT  
9  1970-01-01 00:25:33  
10 1970-01-01 00:03:50

我似乎无法获得差异的秒数。我尝试过:

>> findTheDiff = lambda x: x.diff().astype(np.int64)

在上面的lambda的地方,但这并没有什么区别

我希望'1970-01-01 00:01:30'变成'90'

谢谢你的帮助


Tags: lambda用户indfdatetime记录事件diff
2条回答

在本例中,transform()似乎没有返回与已知issue相关的正确数据类型

使用transform()确实应该在这里工作,但是,考虑到不稳定的行为,解决方法是尝试以下方法:

>> df.sort_values(by='DATETIME').groupby('ID3')['DATETIME'].diff().dt.total_seconds()
Out[168]:
0         NaN
1         NaN
2         NaN
3     17767.0
4         NaN
5       296.0
6        90.0
7       375.0
8         NaN
9      1533.0
10      230.0

这还返回一个类似索引的DF(正如transform所做的那样),并且做得很好

原始答案以及有关transform()故障的更多信息可以找到here

diff正在返回具有seconds属性的Timedelta对象

解决方案(可能)

findTheDiff = lambda x: x.diff().seconds

相关问题 更多 >