【Python入門】条件指定による抽出(query関数のまとめ)

query pandas

条件に合ったデータの行を抽出する方法です。
pandasで、列(column)の値を指定することで、データを抽出します。
抽出によってデータ数を減らすことができると、計算コストが小さくなります。
費用や時間が節約できるので、機械学習においても重要な前処理となります。

query関数を使用すると、すっきりとした条件式で抽出ができます。

サンプルデータ

説明に使用するデータを作成します。
pandas.DataFrameに、5行×3列の配列で、値を設定します。

列名データ型
val整数
name文字列
date日付型
import pandas as pd
df_sample = pd.DataFrame({'val': [10,20,30,20,50],
                          'name': ['ABC', 'BCD', 'CDE', 'EDC', 'CBA'],
                          'date': ['2019/1/1', '2019/2/1', '2019/3/1', '2019/4/1', '2019/5/1']})
# 文字列の「date]を、datetime64型に変換
df_sample['date'] = pd.to_datetime(df_sample['date'])
df_sample.head()
        val	name	date
0	10	ABC	2019-01-01
1	20	BCD	2019-02-01
2	30	CDE	2019-03-01
3	20	EDC	2019-04-01
4	50	CBA	2019-05-01

メソッド(query())

pandas.DataFrame.query(‘条件式’, inplace=False)

query関数は、文字列の条件式でpandas.DataFrameを照会します。
デフォルトのパラメータ( inplace=False )は、データのコピーを返します。
データを変更する場合は、パラメータを設定(inplace=True)とします。

条件指定による抽出

query関数の条件式は、文字列で指定します。

<ポイント>

  • 条件式は、シングルコーテーション「’」又は、ダブルコーテーション「”」で囲む
  • 列名は、列名をそのまま使用(シングルコーテーション等で囲まない)
  • 文字列は、 シングルコーテーション「’」又は、ダブルコーテーション「”」で囲む
    ただし、条件式と別の記号を使用する(例: 列名 == 文字列
  • 条件式で変数を使用するときは、変数名の前に「@」を付ける
    条件式は文字列なので、「@」を付けていない変数名は、列名として評価される

比較演算子で条件指定

pandasは、True 又は False を返す式を指定して、特定の行を取得できます。

df_sample[df_sample['val'] == 20]
        val	name	date
1	20	BCD	2019-02-01
3	20	EDC	2019-04-01


query関数を使用して同じ行を抽出します。

df_sample.query('val == 20')
        val	name	date
1	20	BCD	2019-02-01
3	20	EDC	2019-04-01

簡潔な記述で、一致条件の抽出を行うことができました。

同じように、不一致条件で抽出します。

df_sample.query('val != 20')
        val	name	date
0	10	ABC	2019-01-01
2	30	CDE	2019-03-01
4	50	CBA	2019-05-01


列名「name」は文字列なので、条件式の文字列内で、別の引用符で囲みます。

df_sample.query('name == "CDE"')
        val	name	date
2	30	CDE	2019-03-01


列名「date」は日付型なので、 条件式の文字列内で、別の引用符で囲みます。

df_sample.query('date == "2019-01-01"')
    val	name	date
0	10	ABC	2019-01-01


大小を比較する比較演算子を使用して抽出します。

df_sample.query('val >= 40')
    val	date	    name
4	50	2019-05-01	CBA

否定の条件指定

否定は、チルダ「~」ではなく、「not」を使用します。
列名「val」が、(30以上)ではないデータを抽出します。

df_sample[~(df_sample['val'] >= 30)]
        val	name	date
0	10	ABC	2019-01-01
1	20	BCD	2019-02-01
3	20	EDC	2019-04-01


query関数を使用して同じ行を抽出します。

df_sample.query('not val >= 30')
    val	name	date
0	10	ABC	2019-01-01
1	20	BCD	2019-02-01
3	20	EDC	2019-04-01

複数の条件指定による抽出

1つの列に対する複数の条件指定による抽出

pandasは、 True 又は False を返す複数の式を連結して、特定の行を取得できます。

df_sample[((df_sample['val'] >= 20) & (df_sample['val'] <= 40))]
        val	date	        name
1	20	2019-02-01	BCD
2	30	2019-03-01	CDE
3	20	2019-04-01	EDC

列名「val」が、(20以上)かつ(40以下)のデータを抽出しました。
コードから抽出条件が読み取りにくく、配列名「df_sample」を変更すると、3個所を書き換えることになります。

query関数を使用して同じ行を抽出します。

df_sample.query('20 <= val <= 40')
        val	date	        name
1	20	2019-02-01	BCD
2	30	2019-03-01	CDE
3	20	2019-04-01	EDC

簡潔なコードで記述できました。

一致条件は、リストを使用できます。

df_sample.query('val == [10, 30]')
        val	name	date
0	10	ABC	2019-01-01
2	30	CDE	2019-03-01

リストの要素は、or演算子(2つ以上の条件のどれかに一致)なので、
次の式と同じ。

df_sample[((df_sample['val'] == 10) | (df_sample['val'] == 30))]


リストの要素は、文字列も使用できます。
注意する点として、クエリの条件式とは別の引用符で文字列を囲みます。

df_sample.query('name == ["ABC", "CDE"]')
    val	name	date
0	10	ABC	2019-01-01
2	30	CDE	2019-03-01


不一致条件も、リストを使用できます。

df_sample.query('val != [10, 30]')
    val	name	date
1	20	BCD	2019-02-01
3	20	EDC	2019-04-01
4	50	CBA	2019-05-01

リストの要素は、and演算子(2つ以上の条件のどちらにも一致)なので、
次の式と同じ。

df_sample[((df_sample['val'] != 10) & (df_sample['val'] != 30))]

複数の列に対する条件指定による抽出

pandasは、 True 又は False を返す複数の式を連結して、特定の行を取得できます。
複数の列は、それぞれ括弧で囲み、論理演算子(&、|)で連結します。

df_sample[((df_sample['val'] >= 20) & (df_sample['date'] > '2019-03-01'))]
        val	name	date
3	20	EDC	2019-04-01
4	50	CBA	2019-05-01

列名「val」が(20以上)かつ、列名「date」が(2019-03-01より大きい)データを抽出しました。

query関数を使用して同じ行を抽出します。

df_sample.query('val >= 20 & date > "2019-03-01"')
        val	name	date
3	20	EDC	2019-04-01
4	50	CBA	2019-05-01

条件ごとに括弧で囲む必要はありません。
囲んでもOK。
複雑な条件を設定するときは、先に処理する条件を括弧で囲むとよい。
例: (A==0 or B==1) and C>10

「かつ」は、「&」の代わりに「and」を使用できます。
「または」は、「|」の代わりに「or」を使用できます。

df_sample.query('val >= 20 and date > "2019-03-01"')
        val	name	date
3	20	EDC	2019-04-01
4	50	CBA	2019-05-01

変数を使用した条件指定による抽出

条件式で変数を使用するときは、変数名の前に「@」を付けます。

pick_name =["ABC", "CBA"]
df_sample.query('name == @pick_name')
        val	name	date
0	10	ABC	2019-01-01
4	50	CBA	2019-05-01

パラメータ(inplace)の設定

デフォルトでは、パラメータは( inplace=False )なので、データのコピーを返します。
元のデータを変更する場合は、パラメータを(inplace=True)とします。

サンプルデータのコピーを作成し、query関数( inplace=True )で抽出します。

df_sample_copy = df_sample.copy()
df_sample_copy.query('val == 10', inplace=True)
print(df_sample_copy)
        val	name	date
0	10	ABC	2019-01-01

抽出前は5行だったデータが、1行になっています。

inplace=Trueだと、元のデータを変更(破壊)しますので、注意が必要です。

文字列の部分一致による抽出

文字列の「一部分と一致する」行の抽出 は、以下をご確認ください。
【Python入門】文字列の部分一致による抽出(query関数)

まとめ

  • query関数を使用して、pandas.DataFrameからデータを抽出できました
  • query関数で使用する条件式の記述方法がわかりました
  • pandas.DataFrameで条件指定する抽出から、query関数を使った記述に書き換えができるようになりました

query関数を使用すると、簡潔に抽出条件が記述でき、 コードの可読性が高くなります。
特定の列名やデータに欠損があると、エラーになるので使いにくい場合もありますが、抽出にはquery関数を利用することをおすすめします。

関連情報

タイトルとURLをコピーしました