DataFrame 新列按时差拆分会话 - pandas
DataFrame New Column to split sessions by time difference - pandas
我有以下排序的 DataFrame:
import pandas as pd
hits = {'id': ['A','A','A','A','B','B','C','C'],
'datetime': ['2010-01-02 03:00:00','2010-01-02 03:05:10','2010-01-02 03:51:35','2010-01-02 04:40:20',
'2010-01-02 03:29:10','2010-01-02 03:29:15','2010-01-02 03:45:20','2010-01-02 06:10:05'],
'value': [1,2,2,1,1,3,2,4]
}
df = pd.DataFrame(hits, columns = ['id', 'datetime','value'])
df['datetime'] = pd.to_datetime(df['datetime'], format='%Y-%m-%d %H:%M:%S')
print (df)
id datetime value
0 A 2010-01-02 03:00:00 1
1 A 2010-01-02 03:05:10 2
2 A 2010-01-02 03:51:35 2
3 A 2010-01-02 04:40:20 1
4 B 2010-01-02 03:29:10 1
5 B 2010-01-02 03:29:15 3
6 C 2010-01-02 03:45:20 2
7 C 2010-01-02 06:10:05 4
id
列允许我区分唯一用户,但我想更进一步,能够按会话对点击进行分组。一次会话定义为所有用户 activity 在 activity.
中不超过 30 分钟
在我的 DataFrame 中,所需的输出应该是:
id datetime value session
0 A 2010-01-02 03:00:00 1 1
1 A 2010-01-02 03:05:10 2 1
2 A 2010-01-02 03:51:35 2 2
3 A 2010-01-02 04:40:20 1 3
4 B 2010-01-02 03:29:10 1 1
5 B 2010-01-02 03:29:15 3 1
6 C 2010-01-02 03:45:20 2 1
7 C 2010-01-02 06:10:05 4 2
在 SQL
中,我首先使用 lag
来计算 partition by id order by datetime asc
上点击之间的差异,然后在新查询中我将 sum(case when diff > 30min then 1 else 0 end)
,按 id 分区也是。
Pandas 中有类似的东西吗?
在diff
上使用cumsum
与阈值比较来识别由阈值分隔的块是一种常用技术。类似于:
series.diff().gt('30Min').cumsum()
因为你想通过 id 找到块,你只需要将它包装在 groupby()
:
df['session'] = (df.groupby('id')['datetime']
.transform(lambda x: x.diff().gt('30Min').cumsum())
)
输出:
id datetime value session
0 A 2010-01-02 03:00:00 1 0
1 A 2010-01-02 03:05:10 2 0
2 A 2010-01-02 03:51:35 2 1
3 A 2010-01-02 04:40:20 1 2
4 B 2010-01-02 03:29:10 1 0
5 B 2010-01-02 03:29:15 3 0
6 C 2010-01-02 03:45:20 2 0
7 C 2010-01-02 06:10:05 4 1
你可以双打.groupby
:
- 您可以创建一个名为
s
的 boolean series
,它在 id
和 returns True
或 [=17= 上使用 .groupby
] 对于每个组中的每一行,如果大于 30 分钟。
- 然后,您可以再次对您在步骤 1 中创建的
id
进行分组,并 return 使用 .cumsum
的累积计数并加 1,这样您就可以从 1 开始计数共 0
df['session'] = (df.assign(session=(df.groupby('id')['datetime'].diff() > '00:30:00')
.astype(int))
.groupby('id')['session'].cumsum() + 1)
Out[1]:
id datetime value session
0 A 2010-01-02 03:00:00 1 1
1 A 2010-01-02 03:05:10 2 1
2 A 2010-01-02 03:51:35 2 2
3 A 2010-01-02 04:40:20 1 3
4 B 2010-01-02 03:29:10 1 1
5 B 2010-01-02 03:29:15 3 1
6 C 2010-01-02 03:45:20 2 1
7 C 2010-01-02 06:10:05 4 2
我有以下排序的 DataFrame:
import pandas as pd
hits = {'id': ['A','A','A','A','B','B','C','C'],
'datetime': ['2010-01-02 03:00:00','2010-01-02 03:05:10','2010-01-02 03:51:35','2010-01-02 04:40:20',
'2010-01-02 03:29:10','2010-01-02 03:29:15','2010-01-02 03:45:20','2010-01-02 06:10:05'],
'value': [1,2,2,1,1,3,2,4]
}
df = pd.DataFrame(hits, columns = ['id', 'datetime','value'])
df['datetime'] = pd.to_datetime(df['datetime'], format='%Y-%m-%d %H:%M:%S')
print (df)
id datetime value
0 A 2010-01-02 03:00:00 1
1 A 2010-01-02 03:05:10 2
2 A 2010-01-02 03:51:35 2
3 A 2010-01-02 04:40:20 1
4 B 2010-01-02 03:29:10 1
5 B 2010-01-02 03:29:15 3
6 C 2010-01-02 03:45:20 2
7 C 2010-01-02 06:10:05 4
id
列允许我区分唯一用户,但我想更进一步,能够按会话对点击进行分组。一次会话定义为所有用户 activity 在 activity.
在我的 DataFrame 中,所需的输出应该是:
id datetime value session
0 A 2010-01-02 03:00:00 1 1
1 A 2010-01-02 03:05:10 2 1
2 A 2010-01-02 03:51:35 2 2
3 A 2010-01-02 04:40:20 1 3
4 B 2010-01-02 03:29:10 1 1
5 B 2010-01-02 03:29:15 3 1
6 C 2010-01-02 03:45:20 2 1
7 C 2010-01-02 06:10:05 4 2
在 SQL
中,我首先使用 lag
来计算 partition by id order by datetime asc
上点击之间的差异,然后在新查询中我将 sum(case when diff > 30min then 1 else 0 end)
,按 id 分区也是。
Pandas 中有类似的东西吗?
在diff
上使用cumsum
与阈值比较来识别由阈值分隔的块是一种常用技术。类似于:
series.diff().gt('30Min').cumsum()
因为你想通过 id 找到块,你只需要将它包装在 groupby()
:
df['session'] = (df.groupby('id')['datetime']
.transform(lambda x: x.diff().gt('30Min').cumsum())
)
输出:
id datetime value session
0 A 2010-01-02 03:00:00 1 0
1 A 2010-01-02 03:05:10 2 0
2 A 2010-01-02 03:51:35 2 1
3 A 2010-01-02 04:40:20 1 2
4 B 2010-01-02 03:29:10 1 0
5 B 2010-01-02 03:29:15 3 0
6 C 2010-01-02 03:45:20 2 0
7 C 2010-01-02 06:10:05 4 1
你可以双打.groupby
:
- 您可以创建一个名为
s
的boolean series
,它在id
和 returnsTrue
或 [=17= 上使用.groupby
] 对于每个组中的每一行,如果大于 30 分钟。 - 然后,您可以再次对您在步骤 1 中创建的
id
进行分组,并 return 使用.cumsum
的累积计数并加 1,这样您就可以从 1 开始计数共 0
df['session'] = (df.assign(session=(df.groupby('id')['datetime'].diff() > '00:30:00')
.astype(int))
.groupby('id')['session'].cumsum() + 1)
Out[1]:
id datetime value session
0 A 2010-01-02 03:00:00 1 1
1 A 2010-01-02 03:05:10 2 1
2 A 2010-01-02 03:51:35 2 2
3 A 2010-01-02 04:40:20 1 3
4 B 2010-01-02 03:29:10 1 1
5 B 2010-01-02 03:29:15 3 1
6 C 2010-01-02 03:45:20 2 1
7 C 2010-01-02 06:10:05 4 2