如何为熊猫数据框中的不同组分配唯一的ID?

时间:2019-07-10 20:43:20

标签: python pandas datetime pandas-groupby

如何根据特定条件为在熊猫数据框中创建的组分配唯一ID。 例如:我有一个名为df的数据框,其结构如下:名称标识用户,datetime标识用户访问资源的日期/时间。

Name         Datetime 
Bob          26-04-2018 12:00:00 
Claire       26-04-2018 12:00:00 
Bob          26-04-2018 12:10:00 
Bob          26-04-2018 12:30:00 
Grace        27-04-2018 08:30:00 
Bob          27-04-2018 09:30:00 
Bob          27-04-2018 09:40:00 
Bob          27-04-2018 10:00:00 
Bob          27-04-2018 10:30:00 
Bob          27-04-2018 11:30:00

我想为用户创建会话,以便为具有相同名称和日期时间值的用户访问资源不超过30分钟的用户分配一个唯一的会话。但是,如果用户在访问资源时显示超过30分钟的不活动状态,则该用户将在下次访问该资源时被分配一个不同的会话。

我的预期输出将如下所示。

用户Bob在2018年4月27日访问资源的时间是9.30,第二次@ 9.40,第三次@ 10.00,第四次@ 10.30->所有都与会话4关联。但是下一次用户Bob在@ 11.30上访问时差超过30分钟,因为鲍勃不活动超过30分钟,因此下一次会话将分配给他。

Name         Datetime                    Id
Bob          26-04-2018 12:00:00          1
Claire       26-04-2018 12:00:00          2
Bob          26-04-2018 12:10:00          1
Bob          26-04-2018 12:30:00          1
Grace        27-04-2018 08:30:00          3
Bob          27-04-2018 09:30:00          4
Bob          27-04-2018 09:40:00          4
Bob          27-04-2018 10:00:00          4
Bob          27-04-2018 10:30:00          4
Bob          27-04-2018 11:30:00          5

谢谢您的帮助! 链接到上一个问题:How to compare value of second column with same values of first column in pandas dataframe?

2 个答案:

答案 0 :(得分:2)

sort并找到连续动作的时间差('td')。 cumsum布尔序列,用于在上一个30分钟内形成连续动作组。 ngroup标记组。

如果您不关心分组所获得的标签,可以删除分组依据前的sort_index,但这可以确保根据原始顺序对分组进行排序。

df = df.sort_values(['Name', 'Datetime'])
df['td'] = df.Datetime.diff().mask(df.Name.ne(df.Name.shift()))
                             # Only calculate diff within same Name
df['Id'] = (df.sort_index()
              .groupby(['Name', df['td'].gt(pd.Timedelta('30min')).cumsum()], sort=False)
              .ngroup()+1)
df = df.sort_index()

输出:

td为清楚起见

     Name            Datetime       td  Id
0     Bob 2018-04-26 12:00:00      NaT   1
1  Claire 2018-04-26 12:00:00      NaT   2
2     Bob 2018-04-26 12:10:00 00:10:00   1
3     Bob 2018-04-26 12:30:00 00:20:00   1
4   Grace 2018-04-27 08:30:00      NaT   3
5     Bob 2018-04-27 09:30:00 21:00:00   4
6     Bob 2018-04-27 09:40:00 00:10:00   4
7     Bob 2018-04-27 10:00:00 00:20:00   4
8     Bob 2018-04-27 10:30:00 00:30:00   4
9     Bob 2018-04-27 11:30:00 01:00:00   5

答案 1 :(得分:1)

您在底部的解释对理解它很有帮助。

您需要在NamegroupID上进行分组(不要将此groupID与最后的Id混淆),并致电ngroup返回{ {1}}。最主要的是如何定义此Id。要创建groupID,您需要groupIDsort_valuesName中的每个按升序分开。对Datetime进行分组,并找出Name每组(在同一Datetime中)的连续行之间Name中的差异。使用Name检查大于30分钟,使用gt获取cumsumgroupID还原为原始顺序,并分配给sort_index,如下所示:

s

接下来,将s = df.sort_values(['Name','Datetime']).groupby('Name').Datetime.diff() \ .gt(pd.Timedelta(minutes=30)).cumsum().sort_index() Names分组,以保留原始订单并调用sort=False加1。

ngroup