pandas.DataFrame、pandas.Seriesから特定条件のデータを抽出
環境
今回動作の確認を行った際のバージョンは下記の通り
python:3.10.9
pandas:1.5.3
データセット:scikit-learnのirisを使用(scikit-learnは1.2.2)
データセットの準備
前回までと同じirisデータセットを使用して動作を確認していきます。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frameprint(df.head())# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 1 4.9 3.0 ... 0.2 0# 2 4.7 3.2 ... 0.2 0# 3 4.6 3.1 ... 0.2 0# 4 5.0 3.6 ... 0.2 0# [5 rows x 5 columns]
booleanのリストを使用したデータ抽出
pandas.DataFrame、pandas.Seriesは共に[]に[True, False]の様なbooleanのリストを渡すことで特定の行(Trueが指定された行)を抽出することが可能です。
例えば、下記の様に[True, False, True, False, ・・・]というリストを渡すことで偶数行のデータを抽出することが出来ます。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# sepal length (cm)列をSeriesとして抽出s = df['sepal length (cm)']# TrueとFalseが交互に存在するリストを作成bool_list = [True, False]*int(len(df)/2)# データフレームから偶数行のみ抽出print(df[bool_list])# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 2 4.7 3.2 ... 0.2 0# 4 5.0 3.6 ... 0.2 0# 6 4.6 3.4 ... 0.3 0# 8 4.4 2.9 ... 0.2 0# .. ... ... ... ... ...# 140 6.7 3.1 ... 2.4 2# 142 5.8 2.7 ... 1.9 2# 144 6.7 3.3 ... 2.5 2# 146 6.3 2.5 ... 1.9 2# 148 6.2 3.4 ... 2.3 2## [75 rows x 5 columns]# seriesから偶数行のみ抽出print(s[bool_list])# 0 5.1# 2 4.7# 4 5.0# 6 4.6# 8 4.4# ...# 140 6.7# 142 5.8# 144 6.7# 146 6.3# 148 6.2# Name: sepal length (cm), Length: 75, dtype: float64
また、pandas.DataFrame、pandas.Seriesでは比較演算子を使うことで条件に合致する行のみをTrueとして取得することが可能です。
これを使って「sepal length (cm)が5より大きいデータ」を抽出してみます。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# sepal length (cm)列をSeriesとして抽出s = df['sepal length (cm)']# Dataframeからsepal length (cm)が5より大きいデータを選択print(df['sepal length (cm)'] > 5)# 0 True# 1 False# 2 False# 3 False# 4 False# ...# 145 True# 146 True# 147 True# 148 True# 149 True# Name: sepal length (cm), Length: 150, dtype: bool# seriesからsepal length (cm)が5より大きいデータを選択print(s > 5)# 0 True# 1 False# 2 False# 3 False# 4 False# ...# 145 True# 146 True# 147 True# 148 True# 149 True# Name: sepal length (cm), Length: 150, dtype: bool# 上記のリストを使ってDataframeからsepal length (cm)が5より大きいデータのみ抽出print(df[df['sepal length (cm)'] > 5])# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 5 5.4 3.9 ... 0.4 0# 10 5.4 3.7 ... 0.2 0# 14 5.8 4.0 ... 0.2 0# 15 5.7 4.4 ... 0.4 0# .. ... ... ... ... ...# 145 6.7 3.0 ... 2.3 2# 146 6.3 2.5 ... 1.9 2# 147 6.5 3.0 ... 2.0 2# 148 6.2 3.4 ... 2.3 2# 149 5.9 3.0 ... 1.8 2## [118 rows x 5 columns]# 上記のリストを使ってseriesからsepal length (cm)が5より大きいデータのみ抽出print(s[s > 5])# 0 5.1# 5 5.4# 10 5.4# 14 5.8# 15 5.7# ...# 145 6.7# 146 6.3# 147 6.5# 148 6.2# 149 5.9# Name: sepal length (cm), Length: 118, dtype: float64
下記の様に「&」「|」を使用することで複数条件を指定することも可能です。
各条件を()で括らないとエラーとなるので注意が必要です。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# Dataframeからsepal length (cm)が5より大きく5.5より小さいデータのみ抽出print(df[(df['sepal length (cm)'] > 5) & (df['sepal length (cm)'] < 5.5)])# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 5 5.4 3.9 ... 0.4 0# 10 5.4 3.7 ... 0.2 0# 16 5.4 3.9 ... 0.4 0# 17 5.1 3.5 ... 0.3 0# 19 5.1 3.8 ... 0.3 0# 20 5.4 3.4 ... 0.2 0# 21 5.1 3.7 ... 0.4 0# 23 5.1 3.3 ... 0.5 0# 27 5.2 3.5 ... 0.2 0# 28 5.2 3.4 ... 0.2 0# 31 5.4 3.4 ... 0.4 0# 32 5.2 4.1 ... 0.1 0# 39 5.1 3.4 ... 0.2 0# 44 5.1 3.8 ... 0.4 0# 46 5.1 3.8 ... 0.2 0# 48 5.3 3.7 ... 0.2 0# 59 5.2 2.7 ... 1.4 1# 84 5.4 3.0 ... 1.5 1# 98 5.1 2.5 ... 1.1 1## [20 rows x 5 columns]
queryを使用したデータ抽出
pandas.DataFrame.queryを使用することでも条件を指定してデータ抽出を行うことが可能です。
ただしpandas.DataFrame.queryはpandas.DataFrameのみで使用可能です。
普通はquery('5 < 列名')の様な使い方をしますが、今回は列名に空白が入っているためそのままだとエラーが発生します。
今回のデータの様に列名に空白が入っている場合はバッククォート「``」で列をくくる必要があります。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# Dataframeからsepal length (cm)が5より大きく5.5より小さいデータのみ抽出print(df.query('5 < `sepal length (cm)` < 5.5'))# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 5 5.4 3.9 ... 0.4 0# 10 5.4 3.7 ... 0.2 0# 16 5.4 3.9 ... 0.4 0# 17 5.1 3.5 ... 0.3 0# 19 5.1 3.8 ... 0.3 0# 20 5.4 3.4 ... 0.2 0# 21 5.1 3.7 ... 0.4 0# 23 5.1 3.3 ... 0.5 0# 27 5.2 3.5 ... 0.2 0# 28 5.2 3.4 ... 0.2 0# 31 5.4 3.4 ... 0.4 0# 32 5.2 4.1 ... 0.1 0# 39 5.1 3.4 ... 0.2 0# 44 5.1 3.8 ... 0.4 0# 46 5.1 3.8 ... 0.2 0# 48 5.3 3.7 ... 0.2 0# 59 5.2 2.7 ... 1.4 1# 84 5.4 3.0 ... 1.5 1# 98 5.1 2.5 ... 1.1 1## [20 rows x 5 columns]
変数を使用する場合は、「@変数」とすることで条件式に使用することが可能です。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# Dataframeからsepal length (cm)が5より大きく5.5より小さいデータのみ抽出min = 5max = 5.5print(df.query('@min < `sepal length (cm)` < @max'))# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 5 5.4 3.9 ... 0.4 0# 10 5.4 3.7 ... 0.2 0# 16 5.4 3.9 ... 0.4 0# 17 5.1 3.5 ... 0.3 0# 19 5.1 3.8 ... 0.3 0# 20 5.4 3.4 ... 0.2 0# 21 5.1 3.7 ... 0.4 0# 23 5.1 3.3 ... 0.5 0# 27 5.2 3.5 ... 0.2 0# 28 5.2 3.4 ... 0.2 0# 31 5.4 3.4 ... 0.4 0# 32 5.2 4.1 ... 0.1 0# 39 5.1 3.4 ... 0.2 0# 44 5.1 3.8 ... 0.4 0# 46 5.1 3.8 ... 0.2 0# 48 5.3 3.7 ... 0.2 0# 59 5.2 2.7 ... 1.4 1# 84 5.4 3.0 ... 1.5 1# 98 5.1 2.5 ... 1.1 1## [20 rows x 5 columns]
特定の値と一致するデータのみ抽出する場合はリストとinを使って下記の様に記述することもできます。
from sklearn.datasets import load_irisif __name__ == '__main__':df = load_iris(as_frame=True).frame# Dataframeからsepal length (cm)が5.1、5.2のデータのみ抽出print(df.query('`sepal length (cm)` in [5.1, 5.2]'))# sepal length (cm) sepal width (cm) ... petal width (cm) target# 0 5.1 3.5 ... 0.2 0# 17 5.1 3.5 ... 0.3 0# 19 5.1 3.8 ... 0.3 0# 21 5.1 3.7 ... 0.4 0# 23 5.1 3.3 ... 0.5 0# 27 5.2 3.5 ... 0.2 0# 28 5.2 3.4 ... 0.2 0# 32 5.2 4.1 ... 0.1 0# 39 5.1 3.4 ... 0.2 0# 44 5.1 3.8 ... 0.4 0# 46 5.1 3.8 ... 0.2 0# 59 5.2 2.7 ... 1.4 1# 98 5.1 2.5 ... 1.1 1## [13 rows x 5 columns]