写経中に遭遇したscikit-learnのワーニングに対応してみた

# 概要
[あたらしいPythonによるデータ分析の教科書](https://www.amazon.co.jp/dp/4798158348)を写経中に遭遇したワーニングへ対応したことに関する忘備録。

# 環境
- Windows 10 Pro
- Python 3.7.3

# ことの始まり
1. 案件が無いので会社を休業になる
1. 何か勉強しようとPythonと機械学習に挑戦（2019/1～）
1. とりあえず目についた入門書を購入
1. 以下のコマンドで写経に必要なライブラリをインストールしてJupyter Notebook上で進める

```
pip install numpy
pip install pandas
pip install matplotlib
pip install scikit-learn
pip install jupyter
```

# ワーニングの出た根本的原因
本書に記載されたサンプルデータ一式をダウンロードし、`requirements.txt`を見てみると、以下の記載がある。

```
scikit-learn==0.19.1
```

そして現在（2019/05）インストールしたバージョンをチェックすると、以下の通りとなる。

```
scikit-learn==0.21.2
```

# 遭遇したワーニングとその対応
## 4.4 scikit-learn
### 欠損値の補完
``` python
from sklearn.preprocessing import Imputer
# 平均値で欠損値を補完するためのインスタンスを作成する
imp = Imputer(strategy = 'mean', axis = 0)
# 欠損値を補完
imp.fit(df)
imp.transform(df)
```
参考書通りに写経して実行すると

```
DeprecationWarning: Class Imputer is deprecated; Imputer was deprecated in version 0.20 and will be removed in 0.22. Import impute.SimpleImputer from sklearn instead.
warnings.warn(msg, category=DeprecationWarning)
```

のワーニングが表示される。
意味としては、**「Imputerクラスは0.20で廃止予定となっていて、0.22で削除されます。SimpleInputerクラスを使用してください」**ということ。

ワーニングにしたがって、`SimpleImputer`クラスを使うと、ワーニングは表示されない

``` python
from sklearn.impute import SimpleImputer

# 平均値で欠損値を補完するためのインスタンスを作成する
imp = SimpleImputer(strategy = 'mean')
# 欠損値を補完
imp.fit(df)
imp.transform(df)
```

#### [sklearn.preprocessing.Inputer](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.Imputer.html#sklearn.preprocessing.Imputer)クラス
～0.19までで欠損値補完に使用するクラス。

- `strategy `キーワード引数：文字列をとり、欠損値の補完方法を指定する。デフォルトは`"mean"`。
  - "mean" ：平均値
  - "median"：中央値
  - "most_frequent"：最頻値

- `axis`キーワード引数：数値をとり、補完の方向を指定する。デフォルトは`0`。
  - 0：列方向
  - 1：行方向


#### [sklearn.impute.SimpleImputer](https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html)クラス
0.20以降で欠損値補完に使用するクラス。

- `strategy`キーワード引数：文字列をとり、欠損値の補完方法を指定する。デフォルトは`"mean"`。
    - "mean"：平均値
    - "median"：中央値
    - "most_frequent"：最頻値
    - "constant"：`fill_value`キーワード引数で指定した値（`fill_value`キーワード引数を指定しない場合はデフォルトの`None`）

*※`axis`キーワード引数は存在せず、列方向の補完のみを行う*

### One-hotエンコーディング
~~~python
from sklearn.preprocessing import LabelEncoder, OneHotEncoder

# DataFrameをコピー
df_ohe = df.copy()

# ラベルエンコーダのインスタンス化
le = LabelEncoder()
# 英語のa,b,cを1,2,3に変換
df_ohe['B'] = le.fit_transform(df_ohe['B'])

# One-hotエンコーダのインスタンス化
ohe = OneHotEncoder(categorical_features = [1])
# One-hotエンコーディング
ohe.fit_transform(df_ohe).toarray()
~~~

参考書通りに写経して実行すると

~~~
FutureWarning: The handling of integer data will change in version 0.22. Currently, the categories are determined based on the range [0, max(values)], while in the future they will be determined based on the unique values.
If you want the future behaviour and silence this warning, you can specify "categories='auto'".
In case you used a LabelEncoder before this OneHotEncoder to convert the categories to integers, then you can now use the OneHotEncoder directly.
  warnings.warn(msg, FutureWarning)

DeprecationWarning: The 'categorical_features' keyword is deprecated in version 0.20 and will be removed in 0.22. You can use the ColumnTransformer instead.
  "use the ColumnTransformer instead.", DeprecationWarning)
~~~

のワーニングが表示される。
全体の意味としては**「`categorical_features`キーワードは0.20で廃止予定となっていて、0.22で削除されます。`ColumnTransformer`を使用してください」**ということらしい。

ワーニングに従って、`ColumnTransformer`を使用すると、ワーニングは表示されない。
[scikit-learn公式：`ColumnTransformer`のUsers Guide](https://scikit-learn.org/stable/modules/compose.html#column-transformer)

~~~python
from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction.text import CountVectorizer

# DataFrameをコピー
df_ohe = df.copy()
print(df_ohe)

# ColumnTransformerのインスタンス化
ct = ColumnTransformer([('B_x', CountVectorizer(analyzer=lambda x: [x]), 'B')],
    remainder = 'passthrough')
ct.fit_transform(df_ohe)
~~~


#### [sklearn.preprocessing.OneHotEncoder](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html)クラス
～0.19までで、One-Hotエンコードを行うためのクラス。

- `categorical_features`キーワード引数：どの列をOne-Hotエンコードの対象とするかを指定する<br />**0.20で廃止予定、0.22で削除予定**


#### [sklearn.compose.ColumnTransformer](https://scikit-learn.org/stable/modules/generated/sklearn.compose.ColumnTransformer.html)クラス
DataFrameの列の変更を行うためのクラス。

- 第1引数：リストで[`変換後の列名パターン名称`, `列の変換方法`, `対象となる列`]を指定する。
- `remainder`キーワード引数：文字列をとり、変更しない列の戻り値での取り扱いを指定する。デフォルトは`drop`。
    - `drop`：変更しない列を取り除いた配列を戻り値とする
    - `passthrough`：変更しない列を含めた配列を戻り値とする


#### [sklearn.feature_extraction.text.CountVectorizer](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html)クラス
文章から単語または文字の出現の有無をマトリックス化するためのクラス。

- `analyzer`キーワード引数：文字列または呼び出し可能オブジェクトをとり、N-gramを文字によって行うか、単語によって行うか、あるいはその他の方法で行うかを指定する。
    - `word`：単語を用いたN-gramを使用する。
    - `char`：文字を用いたN-gramを使用する。
    - `char_wb`：文章内の文字のみを用いたN-gramを使用する。
    - 呼び出し可能オブジェクト：文章を受け取り、抽出結果を返す。