Pandas按sampleid分组,筛选purity最优且error最小的行
Pandas分组筛选:高纯度且低误差的最优行
问题描述
现有如下结构的Pandas DataFrame:
sampleid ploidy purity error 0 1962666_A1 2 0.05 0.330501 1 1962666_A1 2 0.09 0.337803 2 1962666_A1 2 0.97 0.991373 3 1962666_A1 3 0.05 0.283901 4 1962666_A1 3 0.10 0.331267 1233 1640057_030959B2_P5 5 0.11 0.359961 1234 1640057_030959B2_P5 5 0.13 0.395113 1235 1640057_030959B2_P5 5 0.19 0.408185 1236 1640057_030959B2_P5 5 0.34 0.437057 1237 1640057_030959B2_P5 5 1.00 0.523207
需要按sampleid分组,为每个组筛选出purity尽可能大且对应error最小的行,同时保留ploidy列。例如第一个组中,索引4的行符合条件(purity=0.10,error=0.331267),而非索引2的行(尽管purity最高,但error过大)。
此前尝试的df.groupby("sampleid").agg({"purity": "max", "error": "min"})会提取不同行的极值,无法得到同一行的结果;使用scipy.argrelextrema只能单条件筛选,均不满足需求。
解决方案
核心思路是先过滤掉每个分组中error异常大的行(避免选中purity高但error离谱的行),再在剩余行中选择purity最大、error最小的行。具体实现如下:
步骤1:定义分组处理函数
使用四分位距(IQR)法识别error的异常值,过滤后排序选最优行:
import pandas as pd def select_optimal_row(group): # 计算error的四分位距,确定异常值上限 q1 = group['error'].quantile(0.25) q3 = group['error'].quantile(0.75) iqr = q3 - q1 upper_threshold = q3 + 1.5 * iqr # 过滤掉error超过阈值的异常行 filtered_group = group[group['error'] <= upper_threshold] # 若过滤后无数据,退而求其次选原组中purity最大且error最小的行 if filtered_group.empty: return group.sort_values(['purity', 'error'], ascending=[False, True]).iloc[0] # 按purity降序、error升序排序,取第一行 return filtered_group.sort_values(['purity', 'error'], ascending=[False, True]).iloc[0]
步骤2:应用函数到分组
# 假设原始DataFrame名为df result = df.groupby('sampleid', group_keys=False).apply(select_optimal_row)
结果说明
- 第一个分组
1962666_A1会过滤掉error=0.991373的行(索引2),剩余行中purity最大的是索引4的行,符合需求。 - 第二个分组
1640057_030959B2_P5会过滤掉error=0.523207的行(索引1237),剩余行中purity最大的是索引1236的行。
如果你的“error过大”的判断标准不同(比如固定阈值),只需修改upper_threshold的计算逻辑即可。
内容的提问来源于stack exchange,提问作者Einar
相关产品推荐
相关产品推荐

