如何为 pandas 数据框中的不同组分配唯一 ID?
Posted
技术标签:
【中文标题】如何为 pandas 数据框中的不同组分配唯一 ID?【英文标题】:How to assign a unique ID for different groups in pandas dataframe? 【发布时间】:2019-11-20 12:47:34 【问题描述】:如何根据特定条件为在 pandas 数据框中创建的组分配唯一 ID。 例如:我有一个名为 df 的数据框,其结构如下:Name 标识用户,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 分钟,因为 Bob 已经超过 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?
【问题讨论】:
也刚刚意识到这似乎与您的其他问题相同,只是有一个更好的示例(此处)。 @SergeBallesta 在他对唯一标签组的回答中提供了正确的逻辑。我的解决方案结果非常相似,只是稍微紧凑一些,并且没有合并。您可以考虑在那里接受他的解决方案,或者作为副本关闭。 【参考方案1】:sort
并找出连续动作的时间差 ('td'
)。 cumsum
一个布尔系列,在最后一个动作的 30 分钟内形成一组连续动作。 ngroup
标记组。
如果您不关心组获得哪个标签,则可以删除 groupby 之前的 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
【讨论】:
【参考方案2】:您在底部的解释对理解它非常有帮助。
您需要在Name
和groupID
上进行分组(不要将此groupID
与您的最终Id
混淆)并调用ngroup
以返回Id
。主要是如何定义这个groupID
。要创建groupID
,您需要sort_values
将每个Name
和Datetime
分隔为升序。 Groupby Name
并找出Datetime
每组Name
内连续行之间的差异(在同一Name
内)。使用gt
检查超过 30 分钟,使用cumsum
获得groupID
。 sort_index
反转回原始顺序并分配给s
,如下所示:
s = df.sort_values(['Name','Datetime']).groupby('Name').Datetime.diff() \
.gt(pd.Timedelta(minutes=30)).cumsum().sort_index()
接下来,groupby Name
and s
with sort=False
保留原始订单并致电ngroup
加1。
df['Id'] = df.groupby(['Name', s], sort=False).ngroup().add(1)
Out[834]:
Name Datetime Id
0 Bob 2018-04-26 12:00:00 1
1 Claire 2018-04-26 12:00:00 2
2 Bob 2018-04-26 12:10:00 1
3 Bob 2018-04-26 12:30:00 1
4 Grace 2018-04-27 08:30:00 3
5 Bob 2018-04-27 09:30:00 4
6 Bob 2018-04-27 09:40:00 4
7 Bob 2018-04-27 10:00:00 4
8 Bob 2018-04-27 10:30:00 4
9 Bob 2018-04-27 11:30:00 5
【讨论】:
以上是关于如何为 pandas 数据框中的不同组分配唯一 ID?的主要内容,如果未能解决你的问题,请参考以下文章
Excel:如何为唯一组合分配值/检查大型数据集中的唯一组合