如何使用pandas计算一个组的聚合函数中的NA?

How to count NA's in aggregate function of a group by using pandas?

我有一个如下所示的数据框

df = pd.DataFrame(
    {'stud_id' : [101, 101, 101, 101, 
                  101, 101, 101, 101],
     'sub_code' : ['CSE01', 'CSE01', 'CSE01', 
                   'CSE01', 'CSE02', 'CSE02',
                   'CSE02', 'CSE02'],
     'ques_date' : ['13/11/2020', '10/1/2018','11/11/2017', '27/03/2016', 
                '13/05/2010',  '10/11/2008','11/1/2007', '27/02/2006'],
     'resp_date' : [np.nan, '11/1/2018','14/11/2017', '29/03/2016', 
                np.nan, np.nan,np.nan,'28/02/2006'],
     'marks' : [77, 86, 55, 90, 
                65, 90, 80, 67]}
)
df['ques_date'] = pd.to_datetime(df['ques_date'])
df['resp_date'] = pd.to_datetime(df['resp_date'])
df['date_diff'] = (df['resp_date'] - df['ques_date']).dt.days

我想执行以下操作

a) 对于每个 stud_idsub_code 组合,得到平均值 date_diff.

b) 对于每个 stud_idsub_code 组合,得到 NA 的平均数。 NAs表示没有反应。例如:stud_id = 101 AND sub_code = CSE01 组合在 4 条记录中有 1 个 NA,导致 1/4 = 0.25.

我尝试了以下但不确定如何在聚合函数中获得平均值 NA

df.groupby(['stud_id','sub_code']).agg(stud_total_records = ('stud_id','count'),
                                            avg_resp_time = ('date_diff','mean'),
                                            lack_resp_pct = (df.groupby(['stud_id','sub_code'])['resp_date'].isna().sum()).reset_index(name='NA_cnt')['NA_cnt']/stud_total_records)

我希望我的输出如下所示

更新

使用惰性组:

grp = df.groupby(['stud_id', 'sub_code'])

out = grp.agg(stud_total_records = ('stud_id', 'count'),
              avg_resp_time = ('date_diff', 'mean'),
              lack_resp_pct = ('date_diff', lambda x: sum(x.isna()) / df['date_diff'].count())) \
         .reset_index()
print(out)

# Output
   stud_id sub_code  stud_total_records  avg_resp_time  lack_resp_pct
0      101    CSE01                   4           12.0           0.25
1      101    CSE02                   4            1.0           0.75

旧答案 尝试:

out = df.groupby(['stud_id','sub_code']).agg(stud_total_records = ('stud_id', 'count'),
                                            avg_resp_time = ('date_diff', 'mean'))

out['lack_resp_pct'] = df[df['date_diff'].isna()].value_counts(['stud_id', 'sub_code'], normalize=True)

输出:

>>> out.reset_index()
   stud_id sub_code  stud_total_records  avg_resp_time  lack_resp_pct
0      101    CSE01                   4           12.0           0.25
1      101    CSE02                   4            1.0           0.75