web-dev-qa-db-ja.com

正規表現でpandasの行をフィルタリングする方法

いずれかの列で正規表現を使用してデータフレームをきれいにフィルター処理したいと思います。

不自然な例:

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

正規表現を使用して、fで始まる行にフィルターをかけたいです。最初に行く:

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

それはあまり便利ではありません。しかし、これは私のブールインデックスを取得します:

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

そのため、次の方法で制限を行うことができます。

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

しかし、そうすることで、人工的に正規表現にグループを入れることができ、クリーンな方法ではないようです。これを行うためのより良い方法はありますか?

123
justinvf

代わりに contains を使用してください:

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

データフレームを使用した複数列の検索:

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

これは少し遅れる可能性がありますが、これはパンダで行う方が簡単になりました。 as_indexer=Trueでmatchを呼び出して、ブール値の結果を取得できます。これは(matchcontainsの違いと共に)文書化されています here

10
Michael Siler

文字列処理関数Series.str.startwith()が既にあります。

foo[foo.b.str.startswith('f')]を試してください。

結果:

a   b
1   2   foo
2   3   fat

あなたが期待することだと思います。

9
Erkan Şirin

@ user3136169のすばらしい回答に感謝します。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

正規表現をチェックし、列に適用を使用するブール関数を作成します

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

strスライスを使用する

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