【问题标题】:Filtering a MultiIndex Pandas DataFrame过滤 MultiIndex Pandas DataFrame
【发布时间】:2017-08-25 13:42:35
【问题描述】:

我有一个 MultiIndex Pandas DataFrame,如下所示:

import pandas as pd
import numpy as np

genotype_data = [
                    ['0/1', '120,60', 180, 5, 0.5, '0/1', '200,2', 202, 99, 0.01],
                    ['0/1', '200,20', 60, 99, 0.1, '0/1', '200,50', 250, 99, 0.4],
                    ['0/1', '200,2', 202, 99, 0.01, '0/1', '200,2', 202, 99, 0.01] 
]


genotype_columns = [['Sample1', 'Sample2'], ['GT', 'AD', 'DP', 'GQ', 'AB']]
cols = pd.MultiIndex.from_product(genotype_columns)
genotype = pd.DataFrame(data=genotype_data, columns=cols)

info_columns = [['INFO'], ['AC', 'DEPTH']]
cols = pd.MultiIndex.from_product(info_columns)
info = pd.DataFrame(data=[[12, 100], [23, 200], [40, 40]], columns=cols)

df = pd.concat([info, genotype], axis=1)

我想为至少有一个样本(在本例中为 Sample1 或 Sample2)具有 DP >= 50 且 GQ

我不知道从哪里开始,希望能得到一些帮助。

编辑:

在 jezrael 的帖子的帮助下,我找到了解决方案。代码如下:

genotype = df.ix[:,3:]

DP = genotype.xs('DP', axis=1, level=1)
GQ = genotype.xs('GQ', axis=1, level=1)

conditions = (DP.ge(50) & GQ.le(4)).T.any() 
df = df[conditions]

return df

【问题讨论】:

    标签: python pandas dataframe multi-index


    【解决方案1】:

    我认为你可以使用:

    • filterSamples列
    • 选择xsDP和HQ子集并与ge和lt比较
    • 逻辑and (&) 并通过any 获得至少一个True
    • 通过idxmax 获取第一个True 并通过loc 选择
    #data in sample change for matching (first 99 in HQ in Sample1 was changed to 3)
    
    genotype_data = [
                        ['0/1', '120,60', 180, 5, 0.5, '0/1', '200,2', 202, 99, 0.01],
                        ['0/1', '200,20', 60, 3, 0.1, '0/1', '200,50', 250, 99, 0.4],
                        ['0/1', '200,2', 202, 99, 0.01, '0/1', '200,2', 202, 99, 0.01] 
    ]
    
    
    genotype_columns = [['Sample1', 'Sample2'], ['GT', 'AD', 'DP', 'GQ', 'AB']]
    cols = pd.MultiIndex.from_product(genotype_columns)
    genotype = pd.DataFrame(data=genotype_data, columns=cols)
    
    info_columns = [['INFO'], ['AC', 'DEPTH']]
    cols = pd.MultiIndex.from_product(info_columns)
    info = pd.DataFrame(data=[[12, 100], [23, 200], [40, 40]], columns=cols)
    
    df = pd.concat([info, genotype], axis=1)
    print (df)
      INFO       Sample1                        Sample2                       
        AC DEPTH      GT      AD   DP  GQ    AB      GT      AD   DP  GQ    AB
    0   12   100     0/1  120,60  180   5  0.50     0/1   200,2  202  99  0.01
    1   23   200     0/1  200,20   60   3  0.10     0/1  200,50  250  99  0.40
    2   40    40     0/1   200,2  202  99  0.01     0/1   200,2  202  99  0.01
    
    df1 = df.filter(like='Sample')
    df = df.loc[[(df1.xs('DP', axis=1, level=1).ge(50) & 
                  df1.xs('GQ', axis=1, level=1).lt(4)).any(1).idxmax()]]
    print (df)
      INFO       Sample1                     Sample2                      
        AC DEPTH      GT      AD  DP GQ   AB      GT      AD   DP  GQ   AB
    1   23   200     0/1  200,20  60  3  0.1     0/1  200,50  250  99  0.4
    

    编辑:

    如果需要按条件返回所有行,删除loc和idmax:

    df1 = df.filter(like='Sample')
    #changed condition to lt(10) (<10)
    df = df[(df1.xs('DP', axis=1, level=1).ge(50) & df1.xs('GQ', axis=1, level=1).lt(10)).any(1)]
    print (df)
      INFO       Sample1                      Sample2                       
        AC DEPTH      GT      AD   DP GQ   AB      GT      AD   DP  GQ    AB
    0   12   100     0/1  120,60  180  5  0.5     0/1   200,2  202  99  0.01
    1   23   200     0/1  200,20   60  3  0.1     0/1  200,50  250  99  0.40
    

    【讨论】:

    • 我正在尝试一些奇怪的东西,我可能永远也做不到,因为我很困......所以......
    • 这不太好用。如果我将条件更改为 DP > 0(如下所示),我希望返回所有三列,但是,我只会返回第一个索引(索引 0)。 df = df.loc[[(df1.xs('DP', axis=1, level=1).ge(0)).any(1).idxmax()]]
    • 嗯,idxmax() id 仅用于第一列,我认为如果需要所有行且条件为 True,您可以将其删除。
    • 好的。我设法通过玩弄你给我的东西来得到它。工作代码现在处于编辑问题中。谢谢你的帮助! :-)
    • 超级,我们的想法是一样的,只是我把T.any()改成了any(1)
    【解决方案2】:

    stack第一级,使用query标识索引

    df.loc[df.stack(0).query('DP >= 50 & GQ < 4').unstack().index]
    
      INFO       Sample1                     Sample2                      
        AC DEPTH      GT      AD  DP GQ   AB      GT      AD   DP  GQ   AB
    1   23   200     0/1  200,20  60  3  0.1     0/1  200,50  250  99  0.4
    

    我使用了@jezrael 的设置

    genotype_data = [
                        ['0/1', '120,60', 180, 5, 0.5, '0/1', '200,2', 202, 99, 0.01],
                        ['0/1', '200,20', 60, 3, 0.1, '0/1', '200,50', 250, 99, 0.4],
                        ['0/1', '200,2', 202, 99, 0.01, '0/1', '200,2', 202, 99, 0.01] 
    ]
    
    
    genotype_columns = [['Sample1', 'Sample2'], ['GT', 'AD', 'DP', 'GQ', 'AB']]
    cols = pd.MultiIndex.from_product(genotype_columns)
    genotype = pd.DataFrame(data=genotype_data, columns=cols)
    
    info_columns = [['INFO'], ['AC', 'DEPTH']]
    cols = pd.MultiIndex.from_product(info_columns)
    info = pd.DataFrame(data=[[12, 100], [23, 200], [40, 40]], columns=cols)
    
    df = pd.concat([info, genotype], axis=1)
    

    【讨论】:

      猜你喜欢
      • 2022-12-04
      • 2019-05-20
      • 2016-11-06
      • 1970-01-01
      • 2017-03-28
      • 2021-05-18
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多