我想根据 CSV 文件中特定项目之间的时间差(30 分钟的差异)将 CSV 文件分组为集群。
然后我想使用排序后的数据进行绘图,因此我需要对 CSV 文件进行排序,以便我能够使用新数据调用图表上的 x 和 y 轴。
所以我需要的是按时间对这个列表进行排序并将其分组为 session 。如果时间差不大于30分钟,则考虑一场。如果超过 30 分钟,则被视为新 session 。
因此用户 2222 仅在 1 个 session 中 由于 item_id 0,2 和 1 是在不同日期创建的,因此用户 5555555 将处于 3 个不同的 session 中。
=====================================
Sample dataset in CSV:
=====================================
uuid,created_at,item_id
2222,2017-01-16 10:54:43.386,0
2222,2017-01-16 10:56:25.717,1
2222,2017-01-16 10:55:50.642,2
5555555,2017-01-16 10:54:19.796,3
5555555,2017-01-16 10:55:10.654,1
5555555,2017-01-17 10:54:55.643,2
5555555,2017-01-27 10:56:02.860,0
323232,2017-01-25 10:56:16.432,3
=====================================
MY CODE
=====================================
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def sessions(filename):
data = pd.read_csv(filename, parse_dates=[1])
data_sort= data.sort_values(by=['uuid', 'created_at'])
cluster = (data_sort["created_at"].diff() > pd.Timedelta(minutes=30))
data_sort.groupby(cluster)
#print(data_sort.to_string())
print()
#print(cluster)
#data_sort['c']=cluster
#print(data_sort.to_string())
a=data_sort.groupby(['uuid'])
sessions=[]
for name, group in data_sort.groupby('uuid'):
session=group.groupby(group["created_at"].diff()>pd.Timedelta(minutes=30))
for n,g in session:
sl=g.values.tolist()
sessiondict=dict()
sessiondict['start']=sl[0][1]
sessiondict['end']=sl[-1][1]
sessiondict['uuid']=sl[0][0]
sessiondict['count']=len(sl)
sessions.append([sessiondict['uuid'],
sessiondict['start'],
sessiondict['end'],
sessiondict['count']])
return pd.DataFrame(sessions)
========================================
RESULT
=======================================
0 1 2 3
0 2222 2016-12-25 11:27:22.905 2017-02-01 21:34:10.479 3
1 2222 2016-12-28 09:40:57.271 2017-02-01 21:29:22.404 1
2 5555555 2017-01-05 15:03:52.859 2017-01-16 19:04:01.355 4
3 5555555 2017-01-09 18:45:52.102 2017-01-16 18:30:06.578 2
4 323232 2016-12-12 20:49:47.972 2016-12-12 20:54:34.990 1
... ... ... ... ...
我遇到的问题如下:代码没有考虑第一个 session 。因此,对于用户 5555555,我总共应该有 3 个 session 。 16日1次,17日2次,27日3次。
另一个问题是,我以某种方式将列的名称从 uuid,created_at,item_id 更改为 1, 2,3,如结果中所示。
所以我想更改以下代码,以便每个 session 都有自己的日期。
预期结果应该是
uuid created_at session_id
5555555 2017-01-16 10:54:19 one session id
5555555,2017-01-16 10:55:10
5555555 2017-01-17 10:54:55 2nd session id
5555555 2017-01-25 3rd session id
这样我就可以知道 1 个用户每天有多少个 session ,或者考虑到我们在一个 session 中有 2 个或更多项目, session 持续多长时间。
最佳答案
这本质上是一个岛屿和缺口问题。对于每个 uuid
,如果一行与其前一行之间的时间间隔大于 30 分钟。我们开始一个新的岛屿。
试试这个:
def summarize(group):
return group.assign(
session_id=group['created_at'].diff().div(pd.Timedelta(minutes=1)).gt(30).cumsum()
)
df.sort_values(['uuid', 'created_at']) \
.groupby('uuid').apply(summarize) \
.reset_index(drop=True)
结果:
uuid created_at item_id session_id
0 2222 2017-01-16 10:54:43.386 0 0
1 2222 2017-01-16 10:55:50.642 2 0
2 2222 2017-01-16 10:56:25.717 1 0
3 323232 2017-01-25 10:56:16.432 3 0
4 5555555 2017-01-16 10:54:19.796 3 0
5 5555555 2017-01-16 10:55:10.654 1 0
6 5555555 2017-01-17 10:54:55.643 2 1
7 5555555 2017-01-27 10:56:02.860 0 2
<小时/>
其工作原理如下:
-
diff()
计算当前行与上一行之间的差异,结果是Timedelta
对象 -
div(...)
转换Timedelta
将对象转换为十进制分钟(即 10.6 分钟) -
gt(30)
检查时间间隔是否大于 30 分钟。如果是,则返回True <=> 1
,这会开始一个新的岛屿。 -
cumsum()
获取累积和,其作用是将每一行分配给相应的岛屿。
关于python - 如何在python中按时间间隔对CSV文件进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58574040/