计算每组的平均时差并有条件地乘以另一列值

时间:2017-05-27 13:01:12

标签: python pandas

在我的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)

0 个答案:

没有答案