如何按gene分组,依据val1/val2/val3无重复最值筛选gene_variant?
问题:按优先级规则为每个gene筛选对应的gene_variant?
给定如下DataFrame:
from io import StringIO import pandas as pd data = StringIO('''gene_variant gene val1 val2 val3 b1 b 1 1 1 b2 b 2 11 1 b3 b 3 11 1 c2 c 1 1 1 t1 t 1 1 1 t2 t 12 2 2 t4 t 12 3 2 t5 t 1 4 3 d2 d 11 1 2 d4 d 11 1 1''') df = pd.read_csv(data, sep='\t')
筛选规则
为每个gene筛选对应的gene_variant,规则如下:
- 优先选取
val1最大值无重复时对应的行; - 若
val1最大值存在重复,则选取val2最大值无重复时对应的行; - 若仍有重复,最后选取
val3最大值对应的行。
补充说明:仅当val1的最大值存在重复时,才会考虑val2;同理,仅当val1/val2的最大值均存在重复时,才会考虑val3。每次仅比较一列的数值。
已尝试的方法
我尝试过以下代码,但都没得到预期结果,最终只能通过迭代实现,想找更优方法:
df.groupby('gene').agg(max)
以及:
df.groupby('gene').rank('max')
预期正确输出
b3 3 c2 1 t5 4 d2 2
解决方案
方法一:逐优先级判断(逻辑直观)
完全按照题目规则逐层判断,先检查当前列最大值是否唯一,唯一则直接返回,否则进入下一列判断:
def select_best_row(group): # 第一步:筛选val1最大值的行 val1_max = group['val1'].max() val1_candidates = group[group['val1'] == val1_max] if len(val1_candidates) == 1: return val1_candidates.iloc[0] # 第二步:val1有重复,筛选val2最大值的行 val2_max = val1_candidates['val2'].max() val2_candidates = val1_candidates[val1_candidates['val2'] == val2_max] if len(val2_candidates) == 1: return val2_candidates.iloc[0] # 第三步:val2仍有重复,取val3最大值的行 return val2_candidates[val2_candidates['val3'] == val2_candidates['val3'].max()].iloc[0] # 应用函数并提取需要的列 result = df.groupby('gene').apply(select_best_row)[['gene_variant', 'val3']] print(result.to_string(header=False))
方法二:排序+分组筛选(高效简洁)
通过全局排序确定优先级,再在分组内逐层筛选,利用pandas内置方法减少循环,适合大数据量场景:
# 按gene升序,val1/val2/val3降序排序 sorted_df = df.sort_values(by=['gene', 'val1', 'val2', 'val3'], ascending=[True, False, False, False]) # 分组后按规则筛选 def filter_group(g): # 先取val1最大值的子组 val1_sub = g[g['val1'] == g['val1'].max()] if len(val1_sub) == 1: return val1_sub # val1重复,取val2最大值的子组 val2_sub = val1_sub[val1_sub['val2'] == val1_sub['val2'].max()] if len(val2_sub) == 1: return val2_sub # val2仍重复,取val3最大的行 return val2_sub.nlargest(1, 'val3') result = sorted_df.groupby('gene').apply(filter_group).reset_index(drop=True) print(result[['gene_variant', 'val3']].to_string(header=False))
两种方法均可得到预期输出,方法一逻辑清晰易维护,方法二执行效率更高。
内容的提问来源于stack exchange,提问作者Liam McIntyre
相关产品推荐
相关产品推荐

