【发布时间】:2019-03-07 00:45:12
【问题描述】:
假设我有一个包含两列的 pandas 数据框:ID 和 Days。 DataFrame 在两个变量中按升序排序。例如:
# Initial dataset
data = pd.DataFrame({'id': np.repeat([1, 2 ,3], 4),
'day': [1, 2, 10, 11, 3, 4, 12, 15, 1, 20, 21, 24]})
id day
0 1 1
1 1 2
2 1 10
3 1 11
4 2 3
5 2 4
6 2 12
7 2 15
8 3 1
9 3 20
10 3 21
11 3 24
我想添加第三列,它将为每个 ID*day 提供一个“会话”编号。 “会话”是指一系列天,一个会话的天数之间的差异小于 2 天。例如,序列5,6,7 将被视为一个会话,而5,6,9 将被视为两个会话并应标记为0, 0, 1,即第5 天和第6 天被引用到会话#0,而第9 天被引用到会话#1。
每个新 ID 的会话编号应该从 0 开始。
也就是说,我想要得到的是:
id day session
0 1 1 0
1 1 2 0
2 1 10 1
3 1 11 1
4 2 3 0
5 2 4 0
6 2 12 1
7 2 15 2
8 3 1 0
9 3 20 1
10 3 21 1
11 3 24 2
为了解决这个任务,我使用基本的 for 循环。在这个循环中,我迭代地遍历所有唯一 ID,然后从初始数据集中子集数据块,并为特定 ID 的每一天分配会话编号。我遇到的问题 - 因为初始数据集是数百万行 - 循环需要大量时间!例如,对于 100 万行,我的循环花费大约一分钟,这太多了。
如何提高速度?什么方法都好!如果您知道如何获得所需的结果,例如,使用一些 numpy 矩阵操作可以减少时间 - 也很好......
我的循环代码:
# Get sessions for every id
sessions = []
for i in data.id.unique():
id_data = data['day'][data['id']==i].reset_index(drop=True)
for ind in id_data.index:
if ind == 0:
temp = [0]
elif ((id_data[ind] - id_data[ind - 1]) < 2):
temp.append(temp[ind - 1])
else:
temp.append(temp[ind - 1] + 1)
sessions.extend(temp)
# Add sessions to the table
data['session'] = sessions
【问题讨论】:
-
data['session'] = np.where(data['day'].shift(1) > data['day'], 1, 0)让你开始,session的增量给我带来了一个小问题:) -
介意根据您的数据测试此处提供的所有解决方案,然后根据您的时间安排接受最好的解决方案吗?
-
@coldspeed ,是的,这将是解决问题的一个很好的例子!我可以做到,但我想明天。我的国家现在是晚上,所以我要睡觉了;)