機械学習の前処理 重複行・列の削除、ラベルエンコード

Posted on 2019/09/03 in 機械学習 , Updated on: 2019/09/03

機械学習などで、treeベースモデルを構築する際に、データセットをチェックして、不要なものを削除する必要がある。具体的には、入っている値が全て同じカラム出会ったり、重複した行など、学習において意味のない行を探し、削除する。

値が全く同じであれば、df.T.drop_duplicates()で簡単に削除ができるが、特徴量がカテゴリ変数で、かつラベルが異なっていると、注意が必要になる。単純に各列でラベルエンコードするのではなく、各特徴量の上から下に順番に値をラベル付けしていく必要がある。これは pandas dataframe の factorize() で簡単に実装できる。

この記事では、削除すべき特徴量カラムの効率的な探し方を紹介する。

データフレームの作成

In [1]:
import pandas as pd

df = pd.DataFrame([[13, 2, 2, 'A', 'C'],
                   [13, 3, 3, 'B', 'A'],
                   [13, 4, 4, 'A', 'C'],
                   [13, 5, 5, 'C', 'B']],
                  columns=['x1', 'x2', 'x3', 'x4', 'x5'])
df
Out[1]:
x1 x2 x3 x4 x5
0 13 2 2 A C
1 13 3 3 B A
2 13 4 4 A C
3 13 5 5 C B

このデータフレームには、下記の特徴がある

  1.  x1はすべて値が同じ  =>  学習に必要ないので削除する
  2.  x2, x3は各インデックスにおける値が同じ  =>  一方を削除する
  3.  x4, x5は、カテゴリ変数で、それぞれラベルは異なるが、意味は同じ  =>  一方を削除する

1. 値がすべて同じカラムを探す

nunique()メソッドを利用する。引数としてaxis=をとり、1 なら行で、0 なら列で、ユニークな値の数を調べる。ユニークな値の数が 1 と等しければ、すべての値が同じだとわかる。

In [ ]:
df.nunique(axis=0) == 1

# x1     True
# x2    False
# x3    False
# x4    False
# x5    False
# dtype: bool

2. 各インデックスの値が同じ複数のカラムを削除する

df.T.drop_duplicates()を利用する。データフレームの転置行列にて、同じ行を削除する。下記操作で、x3が削除される。

In [56]:
df.T.drop_duplicates()
Out[56]:
0 1 2 3
x1 13 13 13 13
x2 2 3 4 5
x4 A B A C
x5 C A C B

3. ラベルの異なる同じカテゴリ変数

df.factorize()を利用して、上から順番に数値へエンコードする。このデータフレームにおいては、下記のように各ラベルが変換される。

  • x4 : A => 0, B => 1, C => 2
  • x5 : C => 0, A => 1, B => 2

変換後のデータフレームを確認すると、x4, x5 は同じ特徴量になっていることがわかる。これで上記 2. で実行した方法を使うことで一方を削除することができる。

In [57]:
categorical_feats = ['x4', 'x5']

for f in categorical_feats:
    labels, uniques = pd.factorize(df[f])
    df[f] = labels
df
Out[57]:
x1 x2 x3 x4 x5
0 13 2 2 0 0
1 13 3 3 1 1
2 13 2 2 0 0
3 13 5 5 2 2

1. 2. 3. をすべて実行

In [2]:
# 1.で判明した `x1`カラムを削除
df = df.drop('x1', axis=1)

# 3. カテゴリ変数を持つ'x4'と'x5`に `factorize()`を適用
categorical_feats = ['x4', 'x5']
for f in categorical_feats:
    labels, uniques = pd.factorize(df[f])
    df[f] = labels
    
# 2. 同じ意味を持つ特徴量を削除する x2 == x3, x4 == x5  ==> x3, x5 削除
df = df.T.drop_duplicates().T

df
Out[2]:
x2 x4
0 2 0
1 3 1
2 4 0
3 5 2

これで不要なカラムを削除できた。上記方法を使用すると重複する列が 3 以上あってもまとめて削除することができる。