419 votes

pandas: filtrer les lignes de DataFrame avec l'opérateur de chaînage

La plupart des opérations en pandas peut être accompli avec l'opérateur de chaînage (groupby, aggregate, apply, etc), mais le seul moyen que j'ai trouvé pour filtrer les lignes est par normal support de l'indexation

df_filtered = df[df['column'] == value]

C'est désagréable car il exige que je attribuer df d'une variable avant d'être en mesure de filtrer sur ses valeurs. Est-il quelque chose de plus semblable à la suivante?

df_filtered = df.mask(lambda x: x['column'] == value)

467voto

Wouter Overmeire Points 6676

Je ne suis pas entièrement sûr de ce que vous voulez, et votre dernière ligne de code n'aide pas non plus, mais de toute façon:

"Enchaînés" le filtrage est effectué par le "chaînage" les critères dans le booléen 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

Si vous voulez de la chaîne d'méthodes, vous pouvez ajouter votre propre masque de la méthode et utiliser celui-ci.

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

75voto

Daniel Velkov Points 9244

La réponse de @lodagro est grande. Je voudrais étendre en généralisant le masque de la fonction:

def mask(df, f):
  return df[f(df)]

Ensuite, vous pouvez faire des trucs comme:

df.mask(lambda x: x[0] < 0).mask(lambda x: x[1] > 0)

4voto

dantes_419 Points 64

Si vous souhaitez appliquer l'ensemble de la commune boolean masques ainsi que d'un usage général, masque, vous pouvez chuck suivantes dans un fichier et ensuite il suffit d'attribuer tous comme suit:

pd.DataFrame = apply_masks()

Utilisation:

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

C'est un peu hacky mais il peut rendre les choses un peu plus propre si vous êtes en permanence la coupe et l'évolution des ensembles de données selon des filtres. Il y a également un objectif général de filtre adapté de Daniel Velkov ci-dessus dans le gen_mask fonction que vous pouvez utiliser avec les lambda fonctions ou autrement si vous le souhaitez.

Fichier pour être sauvé (j'utilise 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X