Pandas 时间序列:查找会话中的间隙,并使用单独的 ID 命名每个会话/间隙

Posted

技术标签:

【中文标题】Pandas 时间序列:查找会话中的间隙,并使用单独的 ID 命名每个会话/间隙【英文标题】:Pandas Time series: find gaps in sessions, and name each session/gap with separate ID 【发布时间】:2021-09-07 16:09:37 【问题描述】:

我正在为一个明显简单的任务而苦苦挣扎,希望在这里找到一些帮助!

我有类似以下 DataFrame 的内容。

d = [
['2021-06-01 08:00:00',"A"],
['2021-06-01 09:00:00',"A"],
['2021-06-01 12:00:00',"B"],
['2021-06-01 13:00:00',"B"],
['2021-06-01 18:00:00',"B"],
['2021-06-01 19:00:00',"B"],
['2021-06-01 22:00:00',"C"],
['2021-06-01 23:00:00',"C"]] 

df=pd.DataFrame(data=d, columns=("timestamp", "session"))

我想确定一个会话大于阈值(例如 1 小时)的时间间隔。不应考虑会话之间的时间间隔 为此,我使用了 .diff() 方法来定位间隙。

df["timestamp"]= pd.to_datetime(df["timestamp"])

df["gap"]=df["timestamp"].diff().dt.seconds > 3600

主要任务是在会话中找到一个间隙,并通过重命名部分/会话来将会话分割成片段,例如uuid.uuid4(). 在示例中,它将导致第 5/6 行中的新会话名称。

我的方法是对独特的会话进行迭代,但是当我在“间隙”列中找到 True 时,我无法重命名这些部分。 我想留在“熊猫世界”,因为这是一项大数据任务。

【问题讨论】:

你能提供一个预期输出的例子吗? 【参考方案1】:

你可以这样做:

    修改您的逻辑以使用.groupby()gap 列设置为session 下的分组 使用GroupBy.cumsum() 获取同一会话中的group id(新会话名称)(对于每个大于1 小时的时间间隔,单独使用group id) 使用GroupBy.transform() 为每个组生成 uuid(每个会话的 uuid 不同,同一会话中每个间隙的 uuid 不同)
import uuid

# Keep your existing codes:
df["timestamp"]= pd.to_datetime(df["timestamp"])

# Modify your existing codes:
#df["gap"] = df["timestamp"].diff().dt.seconds > 3600
df["gap"] = df.groupby('session')["timestamp"].diff().dt.seconds > 3600

# New codes:
df['group'] = df.groupby('session')['gap'].cumsum()
df['session_gap_id'] = df.groupby(['session', 'group'], as_index=False)['group'].transform(lambda x: uuid.uuid4())

结果:

这里,每个 session 有不同的会话名称 session_gap_id,会话中每个不同的组也有单独的 session_gap_id,包括第 5/6 行(行索引 4/5)

print(df)

            timestamp session    gap  group                        session_gap_id
0 2021-06-01 08:00:00       A  False      0  3cca414b-6bbf-4474-92c4-a0c8273955d8
1 2021-06-01 09:00:00       A  False      0  3cca414b-6bbf-4474-92c4-a0c8273955d8
2 2021-06-01 12:00:00       B  False      0  9c86305e-fcd6-42c8-b532-39d342a3b35c
3 2021-06-01 13:00:00       B  False      0  9c86305e-fcd6-42c8-b532-39d342a3b35c
4 2021-06-01 18:00:00       B   True      1  0dbcf66c-ce0d-4b01-93e2-978d77348235
5 2021-06-01 19:00:00       B  False      1  0dbcf66c-ce0d-4b01-93e2-978d77348235
6 2021-06-01 22:00:00       C  False      0  9b31532c-55c0-4a66-8719-1edbb9047fba
7 2021-06-01 23:00:00       C  False      0  9b31532c-55c0-4a66-8719-1edbb9047fba

【讨论】:

【参考方案2】: 您可以使用 groupby / transform 来识别会话中的差距 如果没有预期输出的样本,则不清楚通过创建有间隙的行来实现什么目标
d = [
['2021-06-01 08:00:00',"A"],
['2021-06-01 09:00:00',"A"],
['2021-06-01 12:00:00',"B"],
['2021-06-01 13:00:00',"B"],
['2021-06-01 18:00:00',"B"],
['2021-06-01 19:00:00',"B"],
['2021-06-01 22:00:00',"C"],
['2021-06-01 23:00:00',"C"]] 

df=pd.DataFrame(data=d, columns=("timestamp", "session"))
df["timestamp"] = pd.to_datetime(df["timestamp"])

df["gap"] = df.groupby("session")["timestamp"].transform(lambda s: s.shift(-1) > s+pd.Timedelta("1h"))
df

timestamp session gap
2021-06-01 08:00:00 A False
2021-06-01 09:00:00 A False
2021-06-01 12:00:00 B False
2021-06-01 13:00:00 B True
2021-06-01 18:00:00 B False
2021-06-01 19:00:00 B False
2021-06-01 22:00:00 C False
2021-06-01 23:00:00 C False

【讨论】:

以上是关于Pandas 时间序列:查找会话中的间隙,并使用单独的 ID 命名每个会话/间隙的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas绘制带有间隙的时间序列

Pandas - 查找和索引与行序列模式匹配的行

电话间隙 HTML 应用程序可以与 asp.net Mvc Web 服务器建立会话吗

使用 Java 持久性查询语言按顺序查找间隙

使用间隙和孤岛查找连续的时间/日期 - SQL/BigQuery

使用 Pandas 从查找字典中重命名多索引行