LoginSignup
1
0

More than 1 year has passed since last update.

テーブルデータのカテゴリ特徴量の組み合わせ方

Last updated at Posted at 2021-09-07

何が書かれているか

テーブルデータのカテゴリ特徴量を組み合わせることで、相互作用(積)を表す新たなカテゴリ特徴量を作る方法です。
Kaggleのテーブルコンペ参加中に利用しました。

具体的な方法

下記のようなカテゴリ特徴量cat1, cat2, cat3を持つ訓練データtrainを考えます。

cat1 cat2 cat3 cat4
0 A A C B
1 B A D C
2 C B A D
3 D B A C
4 E C B A

目標はそれぞれの特徴量の組み合わせ(積)を作ることです。

combo_1_2 combo_1_3 combo_1_4 combo_2_3 combo_2_4 combo_3_4
0 AA AC AB AC AB CB
1 BA BD BC AD AC DC
2 CB CA CD BA BD AD
3 DB DA DC BA BC AC
4 EC EB EA CB CA BA

また、テストデータとして以下のtestがあるとします。
testにしか含まれない値があります。

cat1 cat2 cat3 cat4
0 A A C E
1 B A D C
2 C B A D
3 D B A C
4 E C B A

itertoolsというビルトインのモジュールを使います。
カラム同士の組み合わせを作ることで特徴量同士の組み合わせを表せます。

itertoolsの使い方は以下の記事を参考にしました。
すごいぞitertoolsくん

combination.py
import pandas as pd
import itertools

train = pd.DataFrame({
    'cat1': ['A', 'B', 'C', 'D', 'E'],
    'cat2': ['A', 'A', 'B', 'B', 'C'],
    'cat3': ['C', 'D', 'A', 'A', 'B'],
    'cat4': ['B', 'C', 'D', 'C', 'A']
})

test = pd.DataFrame({
    'cat1': ['A', 'B', 'C', 'D', 'E'],
    'cat2': ['A', 'A', 'B', 'B', 'C'],
    'cat3': ['C', 'D', 'A', 'A', 'B'],
    'cat4': ['E', 'C', 'D', 'C', 'A']
})

#特徴量のリストを作る
cat_features = ['cat1', 'cat2', 'cat3', 'cat4']

#特徴量の組み合わせ
#引数はリスト(iterable)と組み合わせの長さ
combinations = itertools.combinations(cat_features, 2)

#組み合わせの特徴量の作成
for c in combinations:
    train[f'combo_{c[0]}_{c[1]}'] = train[c[0]].add(train[c[1]])
    test[f'combo_{c[0]}_{c[1]}'] = test[c[0]].add(test[c[1]])

print(train.columns)
--->
 Index(['cat1', 'cat2', 'cat3', 'cat4', 'combo_cat1_cat2', 'combo_cat1_cat3',
       'combo_cat1_cat4', 'combo_cat2_cat3', 'combo_cat2_cat4','combo_cat3_cat4'],
        dtype='object')

#作成した特徴量の確認
combo_features = [col for col in table.columns if 'combo' in col]

print(train[combo_features])
--->
 combo_cat1_cat2 combo_cat1_cat3 combo_cat1_cat4 combo_cat2_cat3  \
0             AA              AC              AB              AC   
1             BA              BD              BC              AD   
2             CB              CA              CD              BA   
3             DB              DA              DC              BA   
4             EC              EB              EA              CB   

  combo_cat2_cat4 combo_cat3_cat4  
0              AB              CB  
1              AC              DC  
2              BD              AD  
3              BC              AC  
4              CA              BA  

print(test[combo_features])
--->
  combo_cat1_cat2 combo_cat1_cat3 combo_cat1_cat4 combo_cat2_cat3  \
0              AA              AC              AE              AC   
1              BA              BD              BC              AD   
2              CB              CA              CD              BA   
3              DB              DA              DC              BA   
4              EC              EB              EA              CB   

  combo_cat2_cat4 combo_cat3_cat4  
0              AE              CE  
1              AC              DC  
2              BD              AD  
3              BC              AC  
4              CA              BA  

テストデータにしか含まれない値もあるため、trainとtestそれぞれに固有の値を含むカラムを抽出してみます。

combination.py

unmatched_features = []

for col in combo_features:
    train_unique = set(train[col].unique())
    test_unique = set(test[col].unique())

    if train_unique != test_unique:
        print(col)
        print('values only in train')
        print(train_unique - test_unique)
        print('values only in test')
        print(test_unique - train_unique)
        print('+'*30)
        unmatched_features.append(col)

--->
combo_cat1_cat4
values only in train
{'AB'}
values only in test
{'AE'}
++++++++++++++++++++++++++++++
combo_cat2_cat4
values only in train
{'AB'}
values only in test
{'AE'}
++++++++++++++++++++++++++++++
combo_cat3_cat4
values only in train
{'CB'}
values only in test
{'CE'}
++++++++++++++++++++++++++++++

print(unmatched_features)
--->
['combo_cat1_cat4', 'combo_cat2_cat4', 'combo_cat3_cat4']

#モデル学習用に使える特徴量を残します。
train = train.drop(unmatched_columns, axis=1)

print(train)
--->
  cat1 cat2 cat3 cat4 combo_cat1_cat2 combo_cat1_cat3 combo_cat2_cat3
0    A    A    C    B              AA              AC              AC
1    B    A    D    C              BA              BD              AD
2    C    B    A    D              CB              CA              BA
3    D    B    A    C              DB              DA              BA
4    E    C    B    A              EC              EB              CB

この後はカテゴリ変数として変換するのですが、target encodingが有効と考えられます。
目的変数の平均を計算するグループがより細分化されるため、より特徴的な傾向を捉えられる可能性が高くなるからです。(出典:Kaggleで勝つデータ分析の技術

より簡単な方法や便利な方法もあると思いますので、教えていただけますと嬉しいです。
Twitter: https://twitter.com/nicephosphorus

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0