数値データとカテゴリデータの補完

欠損のあるデータセットを用いた数値データとカテゴリデータの補完

データの処理を行おうと考えた時に、データに欠損がある場合があります。
そのようなとき、欠損値に対して削除をするのか代入するのかなどといった対処方法について考える必要が生じます。
欠損値に対する処理として最も簡単な方法は欠損値を含む行を削除してしまうことです。
しかし、欠損の仕方によっては削除することで推定時に悪い影響を与えることも考えられます。今回はReNomを使って欠損値を埋める方法を紹介していきたいと思います。

ライブラリのインポート

  • numpy 1.12.1
  • pandas 0.20.3
In [1]:
import numpy as np
import pandas as pd
from renom.utility import completion

データの作成

In [2]:
data_size = 10000
x1 = np.random.randint(0, 500, data_size).reshape(-1, 1)
x2 = x1 + 10
x3 = np.random.randint(0, 500, data_size).reshape(-1, 1)
x4 = np.random.randint(0, 500, data_size).reshape(-1, 1)
x5 = np.random.choice(["One", "Two", "Three"], data_size, replace=True).reshape(-1, 1)
x6 = np.random.choice(["Four", "Five"], data_size, replace=True).reshape(-1, 1)
x = np.concatenate((x1, x2), axis=1)
x = np.concatenate((x, x3), axis=1)
x = np.concatenate((x, x4), axis=1)
x = np.concatenate((x, x5), axis=1)
x = np.concatenate((x, x6), axis=1)
x
Out[2]:
array([['162', '172', '360', '494', 'Two', 'Five'],
       ['404', '414', '242', '263', 'Three', 'Four'],
       ['253', '263', '349', '239', 'Three', 'Five'],
       ...,
       ['458', '468', '114', '427', 'Two', 'Five'],
       ['418', '428', '470', '165', 'Three', 'Five'],
       ['406', '416', '424', '179', 'Three', 'Five']],
      dtype='<U21')

ランダムに欠損したデータの作成

欠損には種類があり、今回は以下の図で説明されているようなMCARとMARからなるデータを作成します。

MCARについては欠損値を含む行の削除については問題ありませんが、MARとMNARについては削除してしまうことでデータの偏りの問題が発生してしまうためMARについては多重代入法による代入が勧められますが、MNARについてはあまり良い対処方法は知られていません。

In [3]:
missing_idx = np.random.permutation(data_size)
missing_idx1 = missing_idx[:1000]
missing_idx2 = missing_idx[-1010:]
missing_idx3 = missing_idx[2000:3050]
df = pd.DataFrame(x)
df.columns = ["x1", "x2", "x3", "x4", "x5", "x6"]
df = df.astype({"x1":float, "x2":float, "x3":float, "x4":float, "x5":str, "x6":str})
X_complete = df.values
df.loc[df["x2"]<50, "x1"] = np.nan
df.iloc[list(missing_idx1), 2] = np.nan
df.iloc[list(missing_idx2), 4] = np.nan
df.iloc[list(missing_idx3), 5] = np.nan
X_incomplete = df.values
X_filled = completion(X_incomplete, mode="mice", impute_type="col")
X_filled
[MICE] Completing matrix with shape (10000, 6)
/home/d_onodera/renom2.0.0/ReNom/renom/layers/loss/sigmoid_cross_entropy.py:18: RuntimeWarning: overflow encountered in exp
  z = 1. / (1. + np.exp(to_value(-lhs)))
/home/d_onodera/renom2.0.0/ReNom/renom/core.py:898: RuntimeWarning: overflow encountered in exp
  ret = getattr(ufunc, method)(*new_inputs, **kwargs)
[MICE] Starting imputation round 10/60, elapsed time 50.013
[MICE] Starting imputation round 20/60, elapsed time 106.384
[MICE] Starting imputation round 30/60, elapsed time 161.984
[MICE] Starting imputation round 40/60, elapsed time 217.537
[MICE] Starting imputation round 50/60, elapsed time 272.959
[MICE] Starting imputation round 60/60, elapsed time 328.623
Out[3]:
array([[162.0, 172.0, 360.0, 494.0, 'One', 'Five'],
       [404.0, 414.0, 242.0, 263.0, 'Three', 'Four'],
       [253.0, 263.0, 349.0, 239.0, 'Three', 'Five'],
       ...,
       [458.0, 468.0, 114.0, 427.0, 'One', 'Five'],
       [418.0, 428.0, 326.0309934976139, 165.0, 'Three', 'Five'],
       [406.0, 416.0, 424.0, 179.0, 'Three', 'Five']], dtype=object)

追加予定

代入の方法には様々な種類があり、今回はMICEといった方法のみの紹介となっています。
場面に応じて使い分けられるように他の手法もこれから追加をしていきたいと考えています。