1. 抽出条件のパラメータ化

データの抽出条件をパラメータ化したい。

こう思ったことが何度もありました。

今までは複雑な条件は対応できなかったり、対応できたとしても実装が複雑になってしまって使い物にならなかったりで諦めてきました。

ただ今回は違います。

抽出条件のパラメータ化をかなり汎用的に対応できて実装もそれなりに簡単にできる方法を考えました。

使用するのは

Example 1. @pandas.pydata.or

です。

1.1. pandas.Series.isinではない

使用するのはpandas.Series.isinではありません。

Series.isinは皆様普通に使いこなしていると思います。

今回は DataFrame.isinを使用する ことが肝です。

1.2. pandas.DataFrame.isinでは引数に辞書型を指定できる

DataFrame.isinでは辞書型を指定できます。

このことによって 異なる列に異なる抽出条件を一括で指定 できます。

今回はこの機能を使って抽出条件のパラメータ化を実装してみます。

2. DataFrame.isinを試してみる

実際に試してみて動作を確認します。

2.1. データの準備

データはseabornのtipsを使用します。

列が多すぎるの使用する3列だけに絞り込んだデータを使用します。

データ作成のコードがこちらです。

sample.py
import pandas as pd
import seaborn as sns
tips = (
    sns.load_dataset('tips')
    [[
        'total_bill',
        'sex',
        'smoker',
    ]]
)

実際のデータがこちらです。

data output
   total_bill     sex smoker
0       16.99  Female     No
1       10.34    Male     No
2       21.01    Male     No
3       23.68    Male     No
4       24.59  Female     No

2.2. リスト型で条件を指定してみる

動作を確認するためリスト型で条件を指定してみます。

sample.py
tips.isin(
    ['Male']
)
result.py
     total_bill    sex  smoker
0         False  False   False
1         False   True   False
2         False   True   False
3         False   True   False
4         False  False   False
..          ...    ...     ...
239       False   True   False
240       False  False   False
241       False   True   False
242       False   True   False
243       False  False   False

対象の列は指定できないので列に関係なく値が’Male’の箇所がTrueになります。

列を指定できないと少し扱いづらいです。

列を指定するためには辞書型の引数を使用 します。

2.3. 辞書型のパラメータを作成する

下記の条件のパラメータを辞書型で作成します

  1. smoker: Yes

  2. sex: Female

sample.py
conditions={
    'smoker': ['Yes'],
    'sex': ['Female'],
}

2.4. 辞書型の条件を適用する

実際に適用してみます。

sample.py
tips.isin(conditions)
output
     total_bill    sex  smoker
0         False   True   False
1         False  False   False
2         False  False   False
3         False  False   False
4         False   True   False
..          ...    ...     ...
239       False  False   False
240       False   True    True
241       False  False    True
242       False  False   False
243       False   True   False

sex==Femaleの箇所がTrue、smoker==Yesの箇所がTrue になっています。

パラメータで指定していない列:total_billも結果に含まれていてすべてがFalseになっています。

指定していない列があると邪魔 なので指定していない列を除外する方法を検討します。

2.5. 条件指定してしない列を除外する

conditions.keys()を使用して関係ない列は除外します。

実際のコードはこうなります。

sample.py
(
    tips
    [
        conditions.keys()
    ]
    .isin(conditions)
)
output
     smoker    sex
0     False   True
1     False  False
2     False  False
3     False  False
4     False   True
..      ...    ...
239   False  False
240    True   True
241    True  False
242   False  False
243   False   True

指定した列だけの結果を取得できました。

2.6. allを使用してand条件を実現する

allを使用してand条件を実現します。

つまり 女性で喫煙者 の場合にTrueを取得します。

コードはこうなります。

sample.py
(
    tips
    [
        conditions.keys()
    ]
    .isin(conditions)
    .all(axis=1)
)
output
0      False
1      False
2      False
3      False
4      False
       ...
239    False
240     True
241    False
242    False
243    False

and条件を実現できました。

2.7. anyを使用してor条件を実現する

anyを使用してor条件を実現します。

つまり 女性あるいは喫煙者 の場合にTrueを取得します。

コードはこうなります。

sample.py
(
    tips
    [
        conditions.keys()
    ]
    .isin(conditions)
    .any(axis=1)
)
output
0       True
1      False
2      False
3      False
4       True
       ...
239    False
240     True
241     True
242    False
243     True

or条件を実現できました。

3. 実際にデータ抽出してみます

試したことをまとめて実際にデータ抽出してみます。

3.1. 女性で喫煙者

女性かつ喫煙者のデータを抽出します。

sample.py
Female_and_smoker=(
    tips
    .loc[
        lambda x: (
            x
            [
                conditions.keys()
            ]
            .isin(conditions)
            .all(axis=1)
        )
    ]
)
Female_and_smoker.head(5)
output
    total_bill     sex smoker
67        3.07  Female    Yes
72       26.86  Female    Yes
73       25.28  Female    Yes
92        5.75  Female    Yes
93       16.32  Female    Yes

3.2. 女性あるいは喫煙者

女性あるいは喫煙者のデータを抽出します。

sample.py
Female_or_smoker=(
    tips
    .loc[
        lambda x: (
            x
            [
                conditions.keys()
            ]
            .isin(conditions)
            .any(axis=1)
        )
    ]
)
Female_or_smoker.tail(10)
output
     total_bill     sex smoker
229       22.12  Female    Yes
230       24.01    Male    Yes
231       15.69    Male    Yes
234       15.53    Male    Yes
236       12.60    Male    Yes
237       32.83    Male    Yes
238       35.83  Female     No
240       27.18  Female    Yes
241       22.67    Male    Yes
243       18.78  Female     No

4. まとめ

複数の列に対する条件を辞書型で指定してデータ抽出できました。

指定した条件は allかanyのどちらかを使用することでand条件にもor条件にもすることが可能 です。

and条件やor条件がネストしてしまう複雑な抽出条件には対応できませんが簡単の抽出条件であれば便利に使えそうです。

今後は 抽出条件を辞書型パラメータで指定することでデータの条件抽出のコード共通化を進めることができそう です。

今回は以上です。