211 votes

Un moyen efficace d'appliquer plusieurs filtres à un DataFrame ou une série pandas.

J'ai un scénario dans lequel un utilisateur veut appliquer plusieurs filtres à un objet DataFrame ou Series Pandas . Essentiellement, je veux enchaîner efficacement un ensemble de filtrages (opérations de comparaison) qui sont spécifiés à l'exécution par l'utilisateur.

  • Les filtres doivent être additif (c'est-à-dire que chaque application devrait réduire les résultats).
  • J'utilise actuellement reindex() (comme ci-dessous) mais cela crée un nouvel objet à chaque fois et copie les données sous-jacentes (si je comprends bien la documentation). Je veux éviter cette copie inutile car elle serait vraiment inefficace lors du filtrage d'une grande série ou d'un DataFrame.
  • Je pense qu'en utilisant apply() , map() ou quelque chose de similaire pourrait être mieux. Je suis assez novice en matière de Pandas et j'essaie encore de m'y retrouver.
  • De plus, j'aimerais étendre cela pour que le dictionnaire transmis peut inclure les colonnes sur lesquelles opérer et filtrer un DataFrame entier sur la base du dictionnaire d'entrée. Cependant, je suppose que ce qui fonctionne pour une série peut facilement être étendu à un cadre de données.

TL;DR

Je veux prendre un dictionnaire de la forme suivante, appliquer chaque opération à un objet Series donné et renvoyer un objet Series "filtré".

relops = {'>=': [1], '<=': [1]}

Exemple long

Je vais commencer par un exemple de ce que j'ai actuellement et filtrer un seul objet Series. Voici la fonction que j'utilise actuellement :

   def apply_relops(series, relops):
        """
        Pass dictionary of relational operators to perform on given series object
        """
        for op, vals in relops.iteritems():
            op_func = ops[op]
            for val in vals:
                filtered = op_func(series, val)
                series = series.reindex(series[filtered])
        return series

L'utilisateur fournit un dictionnaire avec les opérations qu'il souhaite effectuer :

>>> df = pandas.DataFrame({'col1': [0, 1, 2], 'col2': [10, 11, 12]})
>>> print df
>>> print df
   col1  col2
0     0    10
1     1    11
2     2    12

>>> from operator import le, ge
>>> ops ={'>=': ge, '<=': le}
>>> apply_relops(df['col1'], {'>=': [1]})
col1
1       1
2       2
Name: col1
>>> apply_relops(df['col1'], relops = {'>=': [1], '<=': [1]})
col1
1       1
Name: col1

Une fois de plus, le "problème" avec mon approche ci-dessus est que je pense qu'il y a beaucoup de copies inutiles des données pour les étapes intermédiaires.

3voto

Ram Prajapati Points 81

Ous pouvez également sélectionner des lignes sur la base des valeurs d'une colonne qui ne sont pas dans une liste ou un itérable. Nous allons créer une variable booléenne comme précédemment, mais maintenant nous allons nier la variable booléenne en plaçant ~ devant.

Par exemple

list = [1, 0]
df[df.col1.isin(list)]

3voto

wonderkid2 Points 93

Si vous souhaitez vérifier la présence d'une valeur dans plusieurs colonnes, vous pouvez le faire :

df[(df[['HomeTeam', 'AwayTeam']] == 'Fulham').any(axis=1)]

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