在我的previous post中,感谢@MaxU,我能够计算每个用户的日期时间值之间的平均时差(仅当差异大于给定的阈值时。作为后续工作,我想在这个计算中涉及另一列。假设我也有一个长度列:
index | userid | time | length
1 1 22.01.2001 13:00 15
2 1 22.01.2001 14:05 12
3 1 22.01.2001 14:07 13
4 2 22.01.2001 13:00 15
5 2 22.01.2001 14:04 12
6 2 22.01.2001 14:05 11
7 2 22.01.2001 14:10 14
8 3 22.01.2001 13:20 18
9 3 22.01.2001 14:25 17
10 4 22.01.2001 13:37 12
由此,我可以计算连续活动(avg_time_diff
)之间的平均时差,阈值为60分钟:
userid | avg_time_diff
1 2
2 3
3 5
4 0
这个代码是:
In [122]: threshold = 60
...:
...: (df.sort_values('time').groupby('userid')['time']
...: .apply(lambda x: (x.diff().dt.seconds/60)
...: .to_frame('diff')
...: .query("diff < @threshold")['diff'].mean()))
现在,我希望将每个差异与length
列中的相应值进行多次比较,并获取此数据框:
userid | avg_time_diff | new_column
1 2 26 #(2*13)
2 3 40.5 #(1*11 + 5*14)/2 -> see below for the explanation
3 5 85 #(5*17)
4 0 12 #(since only one row for this user)
对于userid = 2 40.5#(1 * 11 + 5 * 14)/ 2 的说明
由于它被丢弃,所以第5和第4之间的时间差(td)被丢弃 大于60. {6}之间的
td
1 。另外,length
第6行的值 11 。然后,我计算1 * 11 = 11.同样, 7日至6日之间td
5 。第7行的length
值为 的 14 即可。然后,我计算5 * 14 = 70.然后,我取平均值。
我一直在尝试自定义之前的代码(下面),但我认为我需要一种不同的方法来完成这项任务。因为,使用下面的代码,我认为我不能在apply
函数中包含'length'值。
In [122]: threshold = 60
...:
...: (df.sort_values('time').groupby('userid')['time', 'length']
...: .apply(lambda x: (x['time'].diff().dt.seconds/60)
...: .to_frame('diff')
...: .query("diff < @threshold")['diff'].mean()))
有什么建议吗?
这是使用 FOR LOOP的解决方案
for student in student_ids:
df = df_all[df_all['username'] == student]
df['time_diff'] = pd.DataFrame(df['time'].diff().dt.seconds/60)
df['time_diff'] = df['time_diff'].fillna(2)#for the first item that has zero time_diff
df.loc[df['time_diff'] > 60, 'time_diff'] = 60
df['xxx'] = df['time_diff'] * df['length']
item = pd.DataFrame(data={'username':[student], 'avg_length':[np.mean(df['xxx'])]})
my_df = my_df.append(item)