【问题标题】:Pandas df how to parse column value to extract string to int with regexPandas df如何解析列值以使用正则表达式将字符串提取为int
【发布时间】:2021-12-04 17:37:38
【问题描述】:

我有一个包含 2 列的 Pandas df:

    name       Count_Relationship
0   allicin    DOWNREGULATE: 1
1   allicin    DOWNREGULATE: 2
2   allicin    UPREGULATE: 1 | DOWNREGULATE: 1
3   aspirin    UPREGULATE: 5 | DOWNREGULATE: 1
4   albuterol  DOWNREGULATE: 1
5   albuterol  UPREGULATE: 3

如果我按“名称”分组并在“Count_Relationship”列中计数,DOWNREGULATE 的数量大于 UPREGULATE 的数量,我只想过滤掉这些行。在这种情况下,大蒜素将具有 DOWREGULATE 1+2+1=4 和 UPREGULATE =1,因此 num_downregulate>num_upregulate,而在其他情况下(阿司匹林、沙丁胺醇)则并非如此。 我想返回这个过滤后的df:

    name      Count_Relationship
0   allicin   DOWNREGULATE: 1
1   allicin   DOWNREGULATE: 2
2   allicin   UPREGULATE: 1 | DOWNREGULATE: 1

Count_Relationship 列是一个字符串,所以我必须解析字符串的数字部分并将其转换为 int。

我试过这个:

    import pandas as pd

    data = {'name': ['allicin', 'allicin', 'allicin', 'aspirin', 'albuterol', 'albuterol'],
    'Count_Relationship': ['DOWNREGULATE: 1', 'DOWNREGULATE: 2', 'UPREGULATE: 1 | DOWNREGULATE: 1', 'UPREGULATE: 5 | DOWNREGULATE: 1', 'DOWNREGULATE: 1' , 'UPREGULATE: 3']
    }

    df = pd.DataFrame(data)

    substances = df["name"].tolist()
    substances = list(set(substances)) # to get the unique names

    result_substances = []
    
    for substance in (substances):
        try:
            numberOfdownregulate = df[(df["name"] == substance) & (\
            (df["Count_Relationship"].str.match(pat = '("DOWNREGULATE:"([0-9]))')).values[0].astype(int)        
        except:
            pass
        try:    
            numberOfupregulate = df[(df["name"] == substance) & (\
            (df["Count_Relationship"].str.match(pat = '("UPREGULATE:"([0-9]))')).values[0].astype(int)
        except:
            pass
    
        result = numberOfdownregulate - numberOfupregulate
        
        if result > 0:
            result_substances.append(substance)


    df_filtered = df[df["name"].isin(result_substances)]

但我在我的正则表达式所在的行 numberOfdownregulate 处收到语法错误。 如何修复算法?非常感谢

【问题讨论】:

    标签: python regex pandas dataframe group-by


    【解决方案1】:

    您可以提取信息,比较上下,并构建一个掩码来选择数据:

    drugs = (df.join(df['Count_Relationship'].str.extractall('(?P<down>(?<=DOWNREGULATE: )\d+)|(?P<up>(?<=UPREGULATE: )\d+)')
                       .groupby(level=0).first().fillna(0).astype(int)
                     )
               .groupby('name').agg({'down': 'sum', 'up': 'sum'})
               .query('down >= up')
               .index
            )
    
    df[df['name'].isin(drugs)]
    

    输出:

          name               Count_Relationship
    0  allicin                  DOWNREGULATE: 1
    1  allicin                  DOWNREGULATE: 2
    2  allicin  UPREGULATE: 1 | DOWNREGULATE: 1
    

    【讨论】:

    • 谢谢!我不希望沙丁胺醇出现在过滤后的 df 中,因为它的 UPREGULATE 关系(它有 3 个)比 DOWNREGULATE(它有 1 个)更多
    • 我明白了,那你要按药物分组,让我看看
    • @Electra 检查更新
    【解决方案2】:

    我建议将 DOWNREGULATE 和 UPREGULATE 值提取到不同的列中,然后应用按名称分组的值的总和并检查哪个更大。

    下面的示例创建了一个名为 UP_gt_DOWN 的附加布尔列,字面意思是 UPREGULATE 大于 DOWNREGULATE:

    df['UPREGULATE'] = df['Count_Relationship'].str.extract(r"UPREGULATE: (\d*)").fillna(0).astype(int)
    df['DOWNREGULATE'] = df['Count_Relationship'].str.extract(r"DOWNREGULATE: (\d*)").fillna(0).astype(int)
    
    summed_df = df.groupby('name').sum()
    summed_df['UP_gt_DOWN'] = summed_df['UPREGULATE'] > summed_df['DOWNREGULATE']
    print(summed_df)
    
    # Output
    #            UPREGULATE  DOWNREGULATE  UP_gt_DOWN
    # name                                           
    # albuterol           3             1        True
    # allicin             1             4       False
    # aspirin             5             1        True
    
    filtered_drugs = summed_df[~summed_df['UP_gt_DOWN']].index
    print(df[df['name'].isin(filtered_drugs)])
    
    # Output
    #       name               Count_Relationship  UPREGULATE  DOWNREGULATE
    # 0  allicin                  DOWNREGULATE: 1           0             1
    # 1  allicin                  DOWNREGULATE: 2           0             2
    # 2  allicin  UPREGULATE: 1 | DOWNREGULATE: 1           1             1
    

    【讨论】:

      猜你喜欢
      • 2017-02-07
      • 2021-12-05
      • 2022-01-12
      • 2013-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多