如何在Pandas中按组减去对应Empty的average值生成norm列
解决多层索引DataFrame按组减去Empty对应值的问题
问题描述
现有一个多层索引的DataFrame,需要为每个Chem+ID组内的所有记录,计算其average值与本组内Dose为Empty的average值的差值,生成新列norm。此前尝试用groupby取组内最小值的方法,但Empty对应的average并非所有组的最小值,因此该方法无效。
原数据
Chem ID Dose average A 23 Control 0.45 Empty 0.33 Positive 0.55 1mM 0.66 B 24 Control 0.67 Empty 0.45 Positive 0.80 1mM 0.70 C 26 Control 0.66 Empty 0.50 Positive 0.78 1mM 0.66 D 29 Control 0.54 Empty 0.24 Positive 0.33 1mM 0.78 E 30 Control 0.66 Empty 0.40 Positive 0.76 1mM 0.56 F 35 Control 0.67 Empty 0.32 Positive 0.43 1mM 0.44
期望输出
Chem ID Dose average norm A 23 Control 0.45 0.12 Empty 0.33 0.00 Positive 0.55 0.22 1mM 0.66 0.33 B 24 Control 0.67 0.22 Empty 0.45 0.00 Positive 0.80 0.35 1mM 0.70 0.25 C 26 Control 0.66 0.16 Empty 0.50 0.00 Positive 0.78 0.28 1mM 0.66 0.16 D 29 Control 0.54 0.30 Empty 0.24 0.00 Positive 0.33 0.09 1mM 0.78 0.54 E 30 Control 0.66 0.26 Empty 0.40 0.00 Positive 0.76 0.36 1mM 0.56 0.16 F 35 Control 0.67 0.35 Empty 0.32 0.00 Positive 0.43 0.11 1mM 0.44 0.12
解决方案
方法1:利用groupby.transform直接计算
通过groupby按Chem和ID分组,在每个组内精准定位Dose为Empty的average值,再让组内所有average减去该基准值:
# 若DataFrame已是多层索引(Chem、ID、Dose为索引) df['norm'] = df.groupby(['Chem', 'ID'])['average'].transform( lambda x: x - x[x.index.get_level_values('Dose') == 'Empty'].iloc[0] ) # 若原数据未设置多层索引,先执行以下步骤: # df = df.set_index(['Chem', 'ID', 'Dose'])
方法2:提取基准值后合并计算
先单独提取每个Chem+ID组对应的Empty基准值,再通过合并将基准值匹配到原表的每条记录,最后计算差值:
# 提取Empty对应的average值,并重命名列 empty_baseline = df[df['Dose'] == 'Empty'][['Chem', 'ID', 'average']].rename(columns={'average': 'empty_avg'}) # 合并基准值到原表 df = df.merge(empty_baseline, on=['Chem', 'ID'], how='left') # 计算norm列并清理临时列 df['norm'] = df['average'] - df['empty_avg'] df = df.drop(columns='empty_avg')
两种方法都能准确获取每个组的Empty基准值,避免了依赖组内最小值的局限性,最终得到符合要求的norm列。
内容的提问来源于stack exchange,提问作者cadillac_carlito
相关产品推荐
相关产品推荐

