Skip to main content
 首页 » 编程设计

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

2025年05月04日21bonelee

我有一些已识别的用户 (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  

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

请您参考如下方法:

编辑

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