web-dev-qa-db-fra.com

Comment filtrer les lignes dans les pandas par regex

Je voudrais filtrer proprement un cadre de données en utilisant regex sur l'une des colonnes.

Pour un exemple artificiel:

In [210]: foo = pd.DataFrame({'a' : [1,2,3,4], 'b' : ['hi', 'foo', 'fat', 'cat']})
In [211]: foo
Out[211]: 
   a    b
0  1   hi
1  2  foo
2  3  fat
3  4  cat

Je veux filtrer les lignes à celles qui commencent par f en utilisant une expression régulière. Tout d'abord aller:

In [213]: foo.b.str.match('f.*')
Out[213]: 
0    []
1    ()
2    ()
3    []

Ce n'est pas trop utile. Cependant cela me donnera mon index booléen:

In [226]: foo.b.str.match('(f.*)').str.len() > 0
Out[226]: 
0    False
1     True
2     True
3    False
Name: b

Donc je pourrais alors faire ma restriction par:

In [229]: foo[foo.b.str.match('(f.*)').str.len() > 0]
Out[229]: 
   a    b
1  2  foo
2  3  fat

Cela me fait cependant mettre artificiellement un groupe dans la regex, et cela ne semble peut-être pas être la meilleure façon de procéder. Y a-t-il une meilleure manière de faire cela?

105
justinvf

Utilisez contient à la place:

In [10]: df.b.str.contains('^f')
Out[10]: 
0    False
1     True
2     True
3    False
Name: b, dtype: bool
132
waitingkuo

Recherche dans plusieurs colonnes avec dataframe:

frame[frame.filename.str.match('*.'+MetaData+'.*') & frame.file_path.str.match('C:\test\test.txt')]
15

Il existe déjà une fonction de traitement de chaîne Series.str.startwith()

Vous devriez essayer foo[foo.b.str.startswith('f')]

Résultat:  

a   b
1   2   foo
2   3   fat

Je pense à ce que tu attends.

9
Erkan Şirin

C'est peut-être un peu tard, mais c'est maintenant plus facile à faire dans les pandas. Vous pouvez appeler match avec as_indexer=True pour obtenir des résultats booléens. Ceci est documenté (avec la différence entre match et contains) ici .

9
Michael Siler

Merci pour l'excellente réponse @ user3136169, voici un exemple montrant comment cela peut être fait en supprimant les valeurs NoneType.

def regex_filter(val):
    if val:
        mo = re.search(regex,val)
        if mo:
            return True
        else:
            return False
    else:
        return False

df_filtered = df[df['col'].apply(regex_filter)]
6
sparrow

Écrire une fonction booléenne qui vérifie la regex et utilise apply sur la colonne

foo[foo['b'].apply(regex_function)]
4
user3136169

Utilisation de la tranche str 

foo[foo.b.str[0]=='f']
Out[18]: 
   a    b
1  2  foo
2  3  fat
0
Wen-Ben