web-dev-qa-db-fra.com

Pandas filtrer les lignes de trame de données par fonction

Je veux filtrer une trame de données par une fonction plus complexe basée sur différentes valeurs de la ligne.

Y a-t-il une possibilité de filtrer DF lignes par une fonction booléenne comme vous pouvez le faire par exemple dans fonction de filtre ES6 ?

Exemple extrêmement simplifié pour illustrer le problème:

import pandas as pd

def filter_fn(row):
    if row['Name'] == 'Alisa' and row['Age'] > 24:
        return False

    return row

d = {
    'Name': ['Alisa', 'Bobby', 'jodha', 'jack', 'raghu', 'Cathrine',
             'Alisa', 'Bobby', 'kumar', 'Alisa', 'Alex', 'Cathrine'],
    'Age': [26, 24, 23, 22, 23, 24, 26, 24, 22, 23, 24, 24],

    'Score': [85, 63, 55, 74, 31, 77, 85, 63, 42, 62, 89, 77]}

df = pd.DataFrame(d, columns=['Name', 'Age', 'Score'])

df = df.apply(filter_fn, axis=1, broadcast=True)

print(df)

J'ai trouvé quelque chose en utilisant le bit apply () qui ne retourne en fait que False/True lignes remplies à l'aide d'une fonction bool, ce qui est attendu.

Ma solution de contournement serait de renvoyer la ligne elle-même lorsque le résultat de la fonction serait True et de renvoyer False sinon. Mais cela nécessiterait un filtrage supplémentaire après cela.

        Name    Age  Score
0      False  False  False
1      Bobby     24     63
2      jodha     23     55
3       jack     22     74
4      raghu     23     31
5   Cathrine     24     77
6      False  False  False
7      Bobby     24     63
8      kumar     22     42
9      Alisa     23     62
10      Alex     24     89
11  Cathrine     24     77
7
Karl Adler

Je pense que la fonction n'est pas nécessaire ici, mieux et surtout plus rapide est l'utilisation boolean indexing :

m = (df['Name'] == 'Alisa') & (df['Age'] > 24)
print(m)
0      True
1     False
2     False
3     False
4     False
5     False
6      True
7     False
8     False
9     False
10    False
11    False
dtype: bool

#invert mask by ~
df1 = df[~m]

Solution de fonction - est nécessaire de renvoyer un booléen uniquement, mieux si un filtrage compliqué - nécessite un retour pour chaque ligne booléenne uniquement:

def filter_fn(row):
    if row['Name'] == 'Alisa' and row['Age'] > 24:
        return False
    else:
        return True

df = pd.DataFrame(d, columns=['Name', 'Age', 'Score'])
m = df.apply(filter_fn, axis=1)
print(m)
0     False
1      True
2      True
3      True
4      True
5      True
6     False
7      True
8      True
9      True
10     True
11     True
dtype: bool

df1 = df[m]
5
jezrael