はじめに
pandasでqueryによるDataFrameの検索を行う場合の記載について、チートシートを作成したかった。
実現方法はいろいろあるが、独断と偏見で使いやすいなと思った方法を記載。
毎回混乱するので営為作成中。随時更新していく予定。
調べながら作っているので違っているところ多数あるかも。
なお、以下サイト曰く、
処理時間や性能を考える場合は、下手に関数を使わないほうが早いらしい。
[クラウドエンジニアのノート]https://tmyoda.hatenablog.com/entry/2020/03/13/185319)
Python
#queryでpriceが300であるものを検索 → もちろん動く
df.query('price==300')
#直接priceが300であるものを検索 → 動くし、早い
df[df['price'] == 300]
まとめ
抽出条件 | 行名(インデックス) | 列名 | 値 |
---|---|---|---|
ある値に一致するものを抽出 | df.loc df.filter df.query |
df.loc df.filter |
df.query |
ある値と一致しないものを抽出 | df.drop df.filter df.query |
df.drop df.filter |
df.query |
あいまい検索 | df.query df.filter |
df.filter | df.query |
大小指定(不等号) | df.query | - | df.query |
定義した関数を利用 | df.query | - | df.query |
こうしてまとめてみるとquery最強。
インデックスと値はqueryでまかなえ、列名を対象とするときloc、drop、filterを使うイメージか。
結局queryは関数や正規表現を利用できるところから、万能感はある。
サンプルコードの前提DF
Python
import pandas as pd
import numpy as np
df = pd.DataFrame({"Name":['田中', '鈴木', '小林', '藤原'],
"Mt":[55, 60, 30, np.nan],
"Jp":[70, 40, 65, 55],
"Sc":[np.nan, 95, np.nan, np.nan],
"So":[38, 47, 61, 82]}).set_index("Name")
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
# 鈴木 60.0 40.0 95.0 47.0
# 小林 30.0 NaN NaN 61.0
# 藤原 NaN 55.0 NaN 82.0
loc
行名、列名を指定し抽出することができる
Python
df.loc[['田中','鈴木'],:]
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
# 鈴木 60.0 40.0 95.0 47.0
Python
df.loc[:,['Mt', 'Sc']]
# Mt Sc
# Name
# 田中 54.0 NaN
# 鈴木 60.0 95.0
# 小林 30.0 NaN
# 藤原 NaN NaN
drop
行名、列名を指定し、指定したもの以外を残し抽出することができる
Python
df.drop(index= ['小林', '藤原'])
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
# 鈴木 60.0 40.0 95.0 47.0
Python
df.drop(columns= ['Mt', 'Sc'])
# Jp So
# Name
# 田中 70.0 NaN
# 鈴木 40.0 47.0
# 小林 NaN 61.0
# 藤原 55.0 82.0
filter
行名、列名を指定し抽出。
正規表現やlikeが利用できる点が特徴。完全一致ならlocやdropと同じ。
Python
df.filter(items=['田中','鈴木'], axis=0)
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
# 鈴木 60.0 40.0 95.0 47.0
Python
df.filter(items=['Mt','Sc'])
# Mt Sc
# Name
# 田中 54.0 NaN
# 鈴木 60.0 95.0
# 小林 30.0 NaN
# 藤原 NaN NaN
Python
df.filter(like='S')
# Sc So
# Name
# 田中 NaN NaN
# 鈴木 95.0 47.0
# 小林 NaN 61.0
# 藤原 NaN 82.0
Python
df.filter(regex="中$", axis=0)
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
query
自由度という面では万能。
Python
df.query("Name == '田中'")
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
Python
df.query("Name in ['田中', '山田']")
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
df.query("Name not in ['田中', '山田']")
# Mt Jp Sc So
# Name
# 鈴木 60.0 40.0 95.0 47.0
# 小林 30.0 NaN NaN 61.0
# 藤原 NaN 55.0 NaN 82.0
Python
df.query("Sc.isna()", engine='python')
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
# 小林 30.0 NaN NaN 61.0
# 藤原 NaN 55.0 NaN 82.0
df.query("Sc.notna()", engine = 'python')
# Mt Jp Sc So
# Name
# 鈴木 60.0 40.0 95.0 47.0
Python
df.query('Jp > 50')
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
# 藤原 NaN 55.0 NaN 82.0
Python
df.query('index.str.contains("田")', engine='python')
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN
df.query('index.str.match("^田")', engine='python')
# Mt Jp Sc So
# Name
# 田中 54.0 70.0 NaN NaN