You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 09:45:33