270 votes

Comment filtrer des lignes dans pandas par regex ?

Je voudrais filtrer proprement un cadre de données en utilisant une expression rationnelle 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 rangées sur celles qui commencent par f en utilisant une regex. Premier essai :

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

Ce n'est pas terriblement utile. Cependant, cela me permettra d'obtenir mon indice booléen :

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

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

Mais cela m'oblige à introduire artificiellement un groupe dans l'expression rationnelle, ce qui ne semble pas être la meilleure solution. Existe-t-il une meilleure façon de procéder ?

288voto

waitingkuo Points 7290

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

58voto

Erkan Şirin Points 188

Il existe déjà une fonction de traitement des chaînes de caractères Series.str.startswith() . Vous devriez essayer foo[foo.b.str.startswith('f')] .

Résultat :

    a   b
1   2   foo
2   3   fat

Je pense ce que vous attendez.

Vous pouvez également utiliser contains avec l'option regex. Par exemple :

foo[foo.b.str.contains('oo', regex= True, na=False)]

Résultat :

    a   b
1   2   foo

na=False est pour éviter les erreurs en cas de valeurs nan, null etc.

29voto

Michael Siler Points 333

C'est peut-être un peu tard, mais il est maintenant plus facile de faire cela dans Pandas en appelant Series.str.match . Le site docs expliquer la différence entre match , fullmatch y contains .

Notez qu'afin d'utiliser les résultats pour l'indexation, il faut définir le paramètre na=False (ou True si vous voulez inclure les NAN dans les résultats).

25voto

sparrow Points 2593

En s'appuyant sur la grande réponse par utilisateur3136169 Voici un exemple de la manière dont on pourrait procéder en supprimant également les valeurs de type 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)]

Vous pouvez également ajouter une expression rationnelle en tant qu'argument :

def regex_filter(val,myregex):
    ...

df_filtered = df[df['col'].apply(regex_filter,regex=myregex)]

21voto

Recherche sur plusieurs colonnes avec un cadre de données :

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

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