根据唯一条目的数量按组计算比例

时间:2017-07-11 19:35:41

标签: python python-3.x pandas

我有一些已识别的用户(id)在某些时间点使用服务。 我正在尝试计算每天某种服务类型的用户比例。在这个示例数据中,我只有一天,但是如果有更多的日子,我想允许代码以相同的方式工作。

day1 = 
datetime_idx            type  id
2016-03-01 05:04:00      C    1
2016-03-01 05:24:00      A    2
2016-03-01 05:29:00      C    3
2016-03-01 05:29:00      B    4
2016-03-01 05:35:00      D    1

day1_usage = day1.groupby('type').resample('D')['id'].nunique().reset_index()

这给了我以下内容:

     type datetime_idx   id
0    A     2016-03-01        1
1    B     2016-03-01        1
2    C     2016-03-01        2
3    D     2016-03-01        1

我尝试以这种方式获得比例:

day1_usage['ratio'] = (day1_usage.groupby(['type','datetime_idx'])['id'].transform(sum) / day1_usage.groupby('datetime_idx')['id'].transform(sum))

这是我得到的输出:

   type    datetime_idx     id  ratio 
0    A     2016-03-01        1    0.2 
1    B     2016-03-01        1    0.2 
2    C     2016-03-01        2    0.4 
3    D     2016-03-01        1    0.2 

但我想要获得的输出是:

   type    datetime_idx     id  ratio 
0    A     2016-03-01        1    0.25 
1    B     2016-03-01        1    0.25 
2    C     2016-03-01        2    0.5 
3    D     2016-03-01        1    0.25 

我的代码除以用户条目的总和,但我希望它除以唯一用户的数量。

3 个答案:

答案 0 :(得分:2)

您似乎需要size

day1_usage['ratio'] = (day1_usage.groupby(['type','datetime_idx'])['id'].transform(sum) / 
                       day1_usage.groupby('datetime_idx')['id'].transform('size'))
print (day1_usage)
  type datetime_idx  id  ratio
0    A   2016-03-01   1   0.25
1    B   2016-03-01   1   0.25
2    C   2016-03-01   2   0.50
3    D   2016-03-01   1   0.25

答案 1 :(得分:2)

修改

import pandas as pd
import numpy as np
from io import StringIO

让我们尝试多天

csv_file = StringIO("""datetime_idx            type  id
2016-03-01 05:04:00      C    1
2016-03-01 05:24:00      A    2
2016-03-01 05:29:00      C    3
2016-03-01 05:29:00      B    4
2016-03-01 05:35:00      D    1
2016-03-03 05:04:00      C    1
2016-03-03 05:24:00      A    2
2016-03-03 05:29:00      C    3
2016-03-03 05:29:00      B    4
2016-03-03 05:35:00      D    1""")        

days = pd.read_csv(csv_file,sep='\s\s+')

days['datetime_idx'] = pd.to_datetime(days.datetime_idx)

days = days.set_index('datetime_idx')

print(days)

                    type  id
datetime_idx                
2016-03-01 05:04:00    C   1
2016-03-01 05:24:00    A   2
2016-03-01 05:29:00    C   3
2016-03-01 05:29:00    B   4
2016-03-01 05:35:00    D   1
2016-03-03 05:04:00    C   1
2016-03-03 05:24:00    A   2
2016-03-03 05:29:00    C   3
2016-03-03 05:29:00    B   4
2016-03-03 05:35:00    D   1

days_usage = days.groupby('type').resample('D')['id'].nunique().to_frame()

days_usage

                   id
type datetime_idx    
A    2016-03-01     1
     2016-03-02     0
     2016-03-03     1
B    2016-03-01     1
     2016-03-02     0
     2016-03-03     1
C    2016-03-01     2
     2016-03-02     0
     2016-03-03     2
D    2016-03-01     1
     2016-03-02     0
     2016-03-03     1

days_usage['ratio'] = (days_usage.unstack(0)
    .div(days.resample('D')['id'].nunique(), axis='index')).fillna(0).stack().swaplevel(0,1)

print(days_usage)

输出:

                      id  ratio
type datetime_idx           
A    2016-03-01     1   0.25
     2016-03-02     0   0.00
     2016-03-03     1   0.25
B    2016-03-01     1   0.25
     2016-03-02     0   0.00
     2016-03-03     1   0.25
C    2016-03-01     2   0.50
     2016-03-02     0   0.00
     2016-03-03     2   0.50
D    2016-03-01     1   0.25
     2016-03-02     0   0.00
     2016-03-03     1   0.25

答案 2 :(得分:1)

由于您已经计算了day1_usage DataFrame,因此计算也可以像以下一样简单:

day1_usage['ratio'] = day1_usage.id / day1.id.nunique()

结果:

 type datetime_idx  id  ratio
0    A   2016-03-01   1   0.25
1    B   2016-03-01   1   0.25
2    C   2016-03-01   2   0.50
3    D   2016-03-01   1   0.25