首页 > 解决方案 > 如何编写一个迭代熊猫数据框组并应用分层条件的函数?

问题描述

我需要编写一个函数来根据一些分层条件过滤数据集。此函数的目的是为一堆蛋白质中的每个蛋白质获取一个注释。

该功能需要执行以下操作,

  1. 按“id”列对蛋白质进行分组
  2. 检查蛋白质组中的每个分析
  3. 以优先方式选择分析(这不是排序问题,因此应按条件顺序给出分析,以便稍后重新排序)。首先,检查 analysis_1 如果它不存在然后取 analysis_2 或 analysis_3 等。
  4. 将该行放入一个新的数据框中。

这是一个将被过滤的数据示例,

df=pd.DataFrame({
'id':      ['Protein_1', 'Protein_1', 'Protein_1', 
          'Protein_2','Protein_2','Protein_2'],
'analysis': ['analysis_6', 'analysis_4', 'analysis_1', 
                 'analysis_3','analysis_2','analysis_5'],
'annotation':['annotation_1', 'annotation_2', 'annotation_3',
              'annotation_1','annotation_2','annotation_3'] })

这是我想看到的输出,

df_filtered= pd.DataFrame({
'id':      ['Protein_1','Protein_2'],
'analysis': ['analysis_1', 'analysis_2'],
'annotation':['annotation_3', 'annotation_2'] })

下面的代码正在运行,但我想通过使用 pandas groupby、apply 和 iterrows 函数来实现。

new_df =pd.DataFrame(columns=df.columns)
protein_id=list(df.id.unique())

for protein in protein_id:

data=df[df["id"] == protein]

if len(data[data["analysis"] =="analysis_1"]) == 0:
    
    if len(data[data["analysis"] =="analysis_2"]) == 0:
        
        if len(data[data["analysis"] =="analysis_3"]) == 0:
            pass
        else:
            data2=data[data["analysis"] =="analysis_3"]
            new_df = pd.concat([new_df,data2])
        
    else:
        data2=data[data["analysis"] =="analysis_2"]
        new_df = pd.concat([new_df,data2])
    
else:
    data2=data[data["analysis"] =="analysis_1"]
    new_df = pd.concat([new_df,data2])
    
new_df

感谢任何帮助!

标签: pandasgroup-byiterationfilteringhierarchical

解决方案


您可以使用矢量化方法来执行此操作,如果analysis列遵循相同的模式,您可以拆分_并获取最后一个整数层次结构:

方法1:(如果每个组可以有重复的最小层次结构)

helper_s = df['analysis'].str.split("_").str[-1].astype(int)
out = df[helper_s.eq((df.assign(helper_s=helper_s)
                 .groupby("id")['helper_s'].transform("min")))]

          id    analysis    annotation
2  Protein_1  analysis_1  annotation_3
4  Protein_2  analysis_2  annotation_2

方法二:

helper_s = df['analysis'].str.split("_").str[-1].astype(int)
out = df.loc[df.assign(helper_s=helper_s).groupby("id")['helper_s'].idxmin()]

          id    analysis    annotation
2  Protein_1  analysis_1  annotation_3
4  Protein_2  analysis_2  annotation_2

推荐阅读