【问题标题】:Efficient way to filter multiple columns on multiple conditions在多个条件下过滤多个列的有效方法
【发布时间】:2021-11-01 19:53:52
【问题描述】:

我有一个看起来像这样的数据框:

pd.DataFrame({
    'A Code': ['123', '234', '345', '234'],
    'B Code': ['345', '123', '234', '123'],
    'X Code': ['987', '765', '765', '876'],
    'Y Code': ['765', '876', '987', '765'], 
    'H Code': ['AB', 'CD', 'EF', 'AB']
})

    A Code  B Code  X Code  Y Code  H Code
0     123     345     987     765     AB
1     234     123     765     876     CD
2     345     234     765     987     EF
3     234     123     876     765     GH

我想找到A CodeB Code123X CodeY Code765 的行,或者H CodeEFGH 的行。

我使用了以下条件:

(
    ((df[df['A Code'] == '123']) | (df[df['B Code'] == '123'])) 
    &
    ((df[df['X Code'] == '765']) | (df[df['Y Code'] == '765']))
)
|
(df[df['H Code'] == 'EF'])

这很有效,但会变得很长而且很乱。

有没有更有效的方法来做到这一点?

【问题讨论】:

    标签: python pandas dataframe filter


    【解决方案1】:

    尝试使用any

    mask = (
            (df[['A Code', 'B Code']] == '123').any(1)
            & (df[['X Code', 'Y Code']] == '765').any(1)
           ) | (df['H Code'].isin(['EF', 'GH']))
    
    print(df[mask])
    

    【讨论】:

      【解决方案2】:

      您可以使用.query()

      df.query("((`A Code` == '123' or `B Code` == '123') and (`X Code` == '765' or `Y Code` == '765')) or `H Code` in ['EF', 'GH']")
      

      如果值是参数,您可以使用@ 语法引用它们:

      a = '123'
      df.query("`A Code` == @a")
      

      【讨论】:

        【解决方案3】:

        这是另一种方式,使用 Series 进行简单匹配(最后一列使用单独的 isin)。当条件数量增加时,这可能会更容易编写:

        # define single conditions
        s = pd.Series(['123','123','765','765'],
                      index=df.columns[:-1])
        
        df[(df[['A Code', 'B Code']].eq(s).any(1)
           &df[['X Code', 'Y Code']].eq(s).any(1)
           )|df['H Code'].isin(['EF', 'GH'])
          ]
        

        【讨论】:

          【解决方案4】:

          您可以根据自己的喜好尝试以下任何一种方法。

          import pandas as pd
          import time
          
          data = pd.DataFrame({
          'A Code': ['123', '234', '345', '234'],
          'B Code': ['345', '123', '234', '123'],
          'X Code': ['987', '765', '765', '876'],
          'Y Code': ['765', '876', '987', '765'], 
          'H Code': ['AB', 'CD', 'EF', 'AB']})
          

          您可以检查以下三种方法-

          方法1-

          a_code_filter = ['123']
          b_code_filter = ['123']
          x_code_filter = ['765']
          y_code_filter = ['765']
          h_code_filter = ['EF']
          
          idx_ab = (data['A Code'].isin(a_code_filter)) | (data['B Code'].isin(b_code_filter))
          idx_xy = (data['X Code'].isin(x_code_filter)) | (data['Y Code'].isin(y_code_filter))
          idx_h = (data['H Code'].isin(h_code_filter))
          
          idx = (idx_ab) & (idx_xy) | (idx_h)
              
          method1_data = data[idx]
          

          方法2-

           method2_data = data[
              ((data['A Code']=='123') | (data['B Code']=='123')) & ((data['X Code']=='765') | (data['Y Code']=='765')) 
             | (data['H Code']=='EF')
           ]
              
          

          方法3-

           method3_data = data.query("(`A Code`=='123' or `B Code`=='123') & (`X Code`=='765' or `Y Code`=='765') | (`H Code`=='EF')")
          

          【讨论】:

          • Method1 和 Method2 比较不正确。在方法 1 中,您仅测量索引,在方法 2 掩码创建 + 索引中。 query() 的性能也取决于数据帧的大小。对于超过 5k-10k 行的数据帧,它应该是最快的方法。
          • 感谢@AlexanderVolkovsky 的澄清。今天学到了一个新东西:)。相应地修改帖子。
          猜你喜欢
          • 1970-01-01
          • 2020-07-07
          • 1970-01-01
          • 2021-08-27
          • 2018-07-16
          • 2017-08-29
          • 1970-01-01
          • 2013-07-21
          • 1970-01-01
          相关资源
          最近更新 更多