pandas入門 DataFrameのフィルタリング

ここではDataFrameに対し、条件を満たす行を抽出する処理について学習します。SQLでいうところのselect文のwhere句に相当します。

pandasのフィルタリングの基礎概念

pandasのフィルタリングは一見色々バリエーションがあって覚えづらいと感じる方が多いですが、基本的な概念を先に理解しておくと理解がスムーズになるかもしれません。

もしよくわからない場合はこのセクションは読み飛ばしててここから読んでください。

bool型シーケンスの指定

まず、DataFrameの添字にindexと同じサイズのbool型のシーケンスを指定すると、Trueとなるものだけ抽出することができます。

無論この説明だけだと意味不明ですので、サンプルを見てみましょう。4行のDataFrameからindexが偶数つまり0、2の行だけ抽出する場合について考えてみます。

# 4行2列のDataFrameを生成する
df = pd.DataFrame([['A', 10], ['B', 20], ['C', 30], ['D', 40]], columns=['col1', 'col2'])
#   col1  col2
# 0    A    10
# 1    B    20
# 2    C    30
# 3    D    40

# 行数と同じだけbool型のシーケンスを作成。0番目と2番目をTrueとする。
l = [True, False, True, False]

# 作ったシーケンスを添え字に指定するとフィルタリングされる。(0番目と2番目が抽出される)
df[l]

#   col1  col2
# 0    A    10
# 2    C    30
# 

サンプルでは、用意したDataFrameに対し、indexと同じサイズ、つまり行数と同じ要素数のbool型のシーケンス(上のサンプルではリストl)を、dfの添字に指定しています。

シーケンスでは0番目と2番目にTrueが設定されていますが、フィルター結果も同様に0番目と2番目に絞られていることが確認できます。

bool型シーケンスの取得

もちろん、このbool型のシーケンスをわざわざ手打ちで作るわけではありません。ここでDataFrameの演算を使用することで、条件に合致するbool型のシーケンス(Series)を取得することができるのです。

例えば、indexが偶数の列を表すシーケンスを取得したい場合は、以下のように記述します。

df.index % 2 == 0
# array([ True, False,  True, False], dtype=bool)

比較すると、シーケンスが返される点が特徴的です。この演算を利用すると、最初のサンプルは以下のように一般化することができます。

df[df.index % 2 == 0]

すこし回りくどい説明ですが、さらに以下の具体例でちゃんと理解が深まると思います。

完全一致するものを抜き出す

特定列で条件に完全一致するものを抽出する場合のサンプルです。DataFrameの列col1の値が’C’のものを抽出してみます。

df = pd.DataFrame([['A', 10], ['B', 20], ['C', 30], ['D', 40]], columns=['col1', 'col2'])
#   col1  col2
# 0    A    10
# 1    B    20
# 2    C    30
# 3    D    40
df[df.col1=='C']

#   col1  col2
# 2    C    30

大なり小なりでフィルタ

特定列で条件より大きいものを抽出する場合のサンプルです。DataFrameの列col2の値が10より大きいものを抽出してみます。

DataFrame自体は前のサンプルと同じものとします。

df[df.col2 > 10]

#   col1  col2
# 1    B    20
# 2    C    30
# 3    D    40

正規表現でフィルタ

細かい説明は割愛させてください。よく使うのでイディオムとして知っておくと便利だと思います。Series.str.containsで正規表現を指定すると該当するbool型シーケンスが取得できます。

たとえば、正規表現「.*A」と合致する行を抽出する場合、以下のように記述します。

cond = df.col1.str.contains('.*A')
# 0     True
# 1    False
# 2    False
# 3    False
# Name: col1, dtype: bool

df[cond]

#   col1  col2
# 0    A    10