Titanicデータを前処理ライブラリDataLinerで処理してみる(Drop編)

# はじめに
データ前処理を簡単に行えるライブラリDataLinerを、Kaggleでも有名なTitanicデータで色々試してみたいと思います。(データ:https://www.kaggle.com/c/titanic/data)
ちなみに、KaggleのTitanicデータではいくつか特徴量が削除されており、ここのデータを見ると他にもいくつか特徴量があるようです。(データ:https://www.openml.org/d/40945)

それでは、早速やっていきましょう。今回はDropXX系の紹介になります。最後にPipelineを使っての処理も紹介します。

# インストール
```
! pip install -U dataliner
```

# Titanicのデータ
まずはtrain.csvを読み込みます。

```python
import pandas as pd
import dataliner as dl

df = pd.read_csv('train.csv')
target_col = 'Survived'

X = df.drop(target_col, axis=1)
y = df[target_col]
```

読み込んだtrainデータはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/79b05e60-d5ea-46df-b4e9-761bb339a246.png)

## DropColumns
指定した列を単純に削除します。例えば乗客番号を表すPassengerIdはモデリングにおいてあまり役に立たないので削除してみます。

```python
trans = dl.DropColumns('PassengerId')
trans.fit_transform(X)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/3781e03f-353f-15ad-2763-2f130ae4ed06.png)
PassengerIdが削除されました。リストを渡して複数を同時に削除することも可能です。

例えばtrainデータとtestデータをくっつけてdf.dropで普通に削除することもできますが、上記のやり方であればミスが起きにくく、何をしているかが明確となります。例えば、テストデータへは以下のように適用できます。

```python
X_test = pd.read_csv('test.csv')
trans.transform(X_test)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/99aad253-e6fe-3787-2d2d-69170bb77689.png)

また、後述しますがscikit-learnのパイプラインと組み合わせることでデータ前処理・特徴量エンジニアリングの流れを効率的かつ抽象的に組み立てることができるようになります。

## DropNoVariance
分散がない、列の中で単一の値しか存在しない特徴量を削除します。Titanicデータにはそのような特徴量がないので、まず作ってみます。

```python
X['Test_Feature'] = 1
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/b69aca36-91e1-0358-dfa3-c1d954789873.png)

では、DropNoVarianceをかけてみます。

```python
trans = dl.DropNoVariance()
trans.fit_transform(X)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/deba52d0-2195-bcf3-2b32-236e625f6117.png)

といった具合です。数値列、カテゴリ列どちらに対しても使用可能で、複数列ある場合はそのすべてを削除します。

## DropHighCardinality
カテゴリ数が非常に多い列を削除します。カテゴリ数が多すぎると適切にEncodingするのが大変で何かと苦労するので、初動ではone-pass通すためにサクッと落としてしまうのも手です。(Kaggleなどではそこから情報を抽出してグループ化するなどしてカーディナリティを下げに行きます)

```python
trans = dl.DropHighCardinality()
trans.fit_transform(X)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/cc6f67d4-6b82-3640-2bc7-680dfa9cadf1.png)


必要であれば、どの列が消されたかは以下のように確認することもできます。

```python
trans.drop_columns
```
>array(['Name', 'Ticket', 'Cabin'], dtype='<U6')

カテゴリ数が非常に多い特徴量が削除されていることがわかります。

## DropLowAUC
単一の特徴量と目的変数とのロジスティック回帰を行い、その結果AUCが特定のしきい値を下回った特徴量を削除します。特徴量選択に使うことができます。
カテゴリ変数の場合は内部的にダミー変数化された上でロジスティック回帰を行います。
通常0.55程度を推奨しますが、今回はわかりやすさのために高めのしきい値を設定します。

```python
trans = dl.DropLowAUC(threshold=0.65)
trans.fit_transform(X, y)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/7a57074d-7b4e-c063-e109-1bc4bdef519b.png)

残ったのはPclass、Sex、FareとどれもTitanicデータでは目的変数との強い相関がわかっているものばかりとなりました。
OneHotEncodingなどを行い次元数が爆発した後に使うと効果的です。

## DropHighCorrelation
ピアソンの相関係数をもとに、相関が高い特徴量同士を洗い出した上で、目的変数との相関がより高い特徴量のみを残して他を削除します。
内容が全く同じ特徴量が複数あった場合もこちらで同時に削除してくれます。
ブースティング木などではそこまで気にしなくても何とかなりますが、線形回帰などを行う場合は正則化していても削除しておくべきでしょう。

```python
trans = dl.DropHighCorrelation(threshold=0.5)
trans.fit_transform(X, y)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/6c5e0616-9b19-c8d7-8f2a-a46fc2003cb8.png)

Fareが消されていますね。


# Pipelineで使う
ここからがこの方式で前処理を行う最大の利点です。今回紹介した5種類のDropをパイプラインで処理してみます。

```python
from sklearn.pipeline import make_pipeline

process = make_pipeline(
    dl.DropColumns('PassengerId'),
    dl.DropNoVariance(),
    dl.DropHighCardinality(),
    dl.DropLowAUC(threshold=0.65),
    dl.DropHighCorrelation(),
)

process.fit_transform(X, y)
```

上記で紹介した処理がすべて行われ、以下のような結果となりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/956cce3c-5740-c1e0-e15c-184592ecca1b.png)

これを、テストデータに対して適用してみます。

```python
X_test = pd.read_csv('test.csv')
process.transform(X_test)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627325/49598074-d819-f231-a239-c8a467d249ad.png)
学習時と同様の処理をあっという間にテストデータにもかけることができました。
あとはPickleとしてでも保存しておけば、次使う時でもサービスのデプロイでもバッチリですね！


# おわりに
ということで今回はDataLinerのDrop系の項目を紹介しました。
次はEncoding系を紹介したいと思います。

Datalinerリリース記事: https://qiita.com/shallowdf20/items/36727c9a18f5be365b37
GitHub: https://github.com/shallowdf20/dataliner
PyPI: https://pypi.org/project/dataliner/