pandas: filter rows of DataFrame with operator chaining

前端 未结 14 2224
悲哀的现实
悲哀的现实 2020-11-22 16:46

Most operations in pandas can be accomplished with operator chaining (groupby, aggregate, apply, etc), but the only way I

相关标签:
14条回答
  • 2020-11-22 17:28

    Filters can be chained using a Pandas query:

    df = pd.DataFrame(np.random.randn(30, 3), columns=['a','b','c'])
    df_filtered = df.query('a > 0').query('0 < b < 2')
    

    Filters can also be combined in a single query:

    df_filtered = df.query('a > 0 and 0 < b < 2')
    
    0 讨论(0)
  • 2020-11-22 17:29

    This is unappealing as it requires I assign df to a variable before being able to filter on its values.

    df[df["column_name"] != 5].groupby("other_column_name")
    

    seems to work: you can nest the [] operator as well. Maybe they added it since you asked the question.

    0 讨论(0)
  • 2020-11-22 17:34

    If you would like to apply all of the common boolean masks as well as a general purpose mask you can chuck the following in a file and then simply assign them all as follows:

    pd.DataFrame = apply_masks()
    

    Usage:

    A = pd.DataFrame(np.random.randn(4, 4), columns=["A", "B", "C", "D"])
    A.le_mask("A", 0.7).ge_mask("B", 0.2)... (May be repeated as necessary
    

    It's a little bit hacky but it can make things a little bit cleaner if you're continuously chopping and changing datasets according to filters. There's also a general purpose filter adapted from Daniel Velkov above in the gen_mask function which you can use with lambda functions or otherwise if desired.

    File to be saved (I use masks.py):

    import pandas as pd
    
    def eq_mask(df, key, value):
        return df[df[key] == value]
    
    def ge_mask(df, key, value):
        return df[df[key] >= value]
    
    def gt_mask(df, key, value):
        return df[df[key] > value]
    
    def le_mask(df, key, value):
        return df[df[key] <= value]
    
    def lt_mask(df, key, value):
        return df[df[key] < value]
    
    def ne_mask(df, key, value):
        return df[df[key] != value]
    
    def gen_mask(df, f):
        return df[f(df)]
    
    def apply_masks():
    
        pd.DataFrame.eq_mask = eq_mask
        pd.DataFrame.ge_mask = ge_mask
        pd.DataFrame.gt_mask = gt_mask
        pd.DataFrame.le_mask = le_mask
        pd.DataFrame.lt_mask = lt_mask
        pd.DataFrame.ne_mask = ne_mask
        pd.DataFrame.gen_mask = gen_mask
    
        return pd.DataFrame
    
    if __name__ == '__main__':
        pass
    
    0 讨论(0)
  • 2020-11-22 17:36

    I'm not entirely sure what you want, and your last line of code does not help either, but anyway:

    "Chained" filtering is done by "chaining" the criteria in the boolean index.

    In [96]: df
    Out[96]:
       A  B  C  D
    a  1  4  9  1
    b  4  5  0  2
    c  5  5  1  0
    d  1  3  9  6
    
    In [99]: df[(df.A == 1) & (df.D == 6)]
    Out[99]:
       A  B  C  D
    d  1  3  9  6
    

    If you want to chain methods, you can add your own mask method and use that one.

    In [90]: def mask(df, key, value):
       ....:     return df[df[key] == value]
       ....:
    
    In [92]: pandas.DataFrame.mask = mask
    
    In [93]: df = pandas.DataFrame(np.random.randint(0, 10, (4,4)), index=list('abcd'), columns=list('ABCD'))
    
    In [95]: df.ix['d','A'] = df.ix['a', 'A']
    
    In [96]: df
    Out[96]:
       A  B  C  D
    a  1  4  9  1
    b  4  5  0  2
    c  5  5  1  0
    d  1  3  9  6
    
    In [97]: df.mask('A', 1)
    Out[97]:
       A  B  C  D
    a  1  4  9  1
    d  1  3  9  6
    
    In [98]: df.mask('A', 1).mask('D', 6)
    Out[98]:
       A  B  C  D
    d  1  3  9  6
    
    0 讨论(0)
  • 2020-11-22 17:37

    You can also leverage the numpy library for logical operations. Its pretty fast.

    df[np.logical_and(df['A'] == 1 ,df['B'] == 6)]
    
    0 讨论(0)
  • 2020-11-22 17:40

    pandas provides two alternatives to Wouter Overmeire's answer which do not require any overriding. One is .loc[.] with a callable, as in

    df_filtered = df.loc[lambda x: x['column'] == value]
    

    the other is .pipe(), as in

    df_filtered = df.pipe(lambda x: x['column'] == value)
    
    0 讨论(0)
提交回复
热议问题