Python × Power BI データ分析事始め【データ加工編】

Python ×　Power BI について、[データ準備編](https://qiita.com/h_kobayashi1125/items/afc55abf7e98581bcab3)と[ビジュアル編](https://qiita.com/h_kobayashi1125/items/e10986ff223306ed9f2f)に分けて取り上げたところですが、
やはり忘れてならないのは前処理の話です。

本記事は、[Microsoft Power BI Advent Calendar 2018](https://qiita.com/advent-calendar/2018/powerbi)として、Power BI × Pythonの前処理、データ加工について少しだけ取り上げます。


# データの前処理

データ分析を本業にする人にとって、前処理の過程は避けて通れません。
いわゆる政府が公開するオープンデータもこんな感じなケースは多々あります。
![図1.jpg](https://qiita-image-store.s3.amazonaws.com/0/165789/bb2d1c02-9792-7d96-7e11-53d678306a63.jpeg)
[Vital Statistics_Vital statistics of Japan_Final data_Population_Yearly_2017](http://www.data.go.jp/data/dataset/mhlw_20181127_1889)

また、マイナスをゼロにするだけでなく、データの価値をプラスにする処理必要です。
機械学習で汎化性能の高いモデルを作るためのダミー化、正規化、欠損処理、
因子分析や主成分分析など、変数の生成・統合、
データの前処理は分析者にとって永遠の課題です。

# 前処理としてのPowerQuery
Power BI Desktopでは、Power Queryによるデータ加工が基本機能であり、大変高機能です。
Power Queryの詳細はこちら
https://support.office.com/ja-jp/article/microsoft-power-query-for-excel-%E3%81%AE%E6%A6%82%E8%A6%81-6e92e2f4-2079-4e1f-bad5-89f6269cd605


しかし、PowerQueryのみだと少し厄介な処理などは、RやPythonのライブラリに頼ることもできるかもしれません。
そこで、Pythonのpandas、sikit-learnライブラリを利用した利便性の高いデータ前処理を、いくつかPower BIで実践します。

# Pythonによるデータ加工
Power BIでPythonによるデータ加工を行う場合、基本はクエリエディター上でPythonの実行処理を以下から行います。

![図2.jpg](https://qiita-image-store.s3.amazonaws.com/0/165789/7b8a8d1d-7a76-9286-c0d8-29d8f2d10dc2.jpeg)

ビジュアル作成と同じく、データモデルが```dataset(pandas.DataFrame)```に格納されています。
加工後のデータフレームを何らかの変数に指定すれば処理後の内容をデータモデルにすることができる仕組みです。

![図3.jpg](https://qiita-image-store.s3.amazonaws.com/0/165789/fd781fa5-6016-667a-080d-0e046f3a4e1a.jpeg)








# ダミー変数化
カテゴリデータを0,1にフラグ化し、数量的に解析できるようにするダミー変数処理はデータ加工に欠かせません。
```pandas```のライブラリに頼り処理してみます。

利用するデータセットは、[UCI Machinelearning Repository](https://archive.ics.uci.edu/ml/index.php)のBankMarketing Datasetを利用します。

このデータフレームの```job```は12個の値をもっており、すべて文字列データであることが分かります。

![図4.jpg](https://qiita-image-store.s3.amazonaws.com/0/165789/1cda902b-ae19-5daa-e00a-e22a614670ea.jpeg)


クエリエディター上で、以下のようにPythonの処理をかませます。
※以下```pandas```と```sklearn```のインポートコードは省略しています。

```python
new_df = pandas.get_dummies(dataset["job"])
```

これで以下の出力を呼び出せます。
![図6.jpg](https://qiita-image-store.s3.amazonaws.com/0/165789/cd4c37a7-b371-129d-8211-17d4f5f02b93.jpeg)

pythonのライブラリを利用すれば、コード１行で面倒なダミー化も実行可能です。


# ラベル作成
続いて、文字列データを数値に置き換えるラベルエンコーダーを試します。
Power BIは文字データも比較的高速ですし、解析には前述のダミー化のほうが利用価値が高いですが、
比較的面倒な処理をローコーディングで実現できます。

```python
le = sklearn.preprocessing.LabelEncoder()
le.fit(bank["job"])
bank["new_job"] = le.transform(bank["job"])
```
以下、```job```列を数値化した列を作成できました。
![図7.jpg](https://qiita-image-store.s3.amazonaws.com/0/165789/49b79305-eb51-c934-7a52-d3d1f7dda87a.jpeg)

# 欠損処理
データ加工において比較的ウェイトが高い課題が欠損処理です。
NULLを特定規則で置き換えるのみならPower BI単体で楽に実行可能ですが、
１レコードずつ、欠損個所の尤もらしい値を代入することは容易ではありません。
そこで、Pythonの機械学習ライブラリを頼り、回帰代入してしまおうということです。

※欠損処理については、Rを利用したほうがより推奨される多重代入という手法が利用できるので、わかるようであればそちらのほうがおススメされます。

※以下はあえてBankMarketingDatasetの```balance```カラムに欠損を生じさせたデータを利用しています。

```python
regr = sklearn.linear_model.LinearRegression()
df = pd.get_dummies(dataset["job"])
df["age"] = dataset["age"]
df["balance"] = dataset["balance"]

df_1 = df.dropna(subset=['balance'])
df_2 = df[df["balance"].isnull()]

regr.fit(df_1.drop(["balance"],axis=1)
        , df_1["balance"])
pred = regr.predict(df_2.drop(["balance"],axis=1))
df_2 = df_2.reset_index().drop("index",axis=1)
df_2["balance"] = pandas.Series(pred)
df = pd.concat([df_1,df_2],ignore_index=True)
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/165789/ab710138-1606-4151-98fb-0e0352ba2182.jpeg" width=500>


無事、欠損値が推定されているのが確認できました。


# おわりに

以上のように、Pythonを利用することで、ライブラリの恩恵を楽に受けることができます。
ただし、実行の重さや個々の実行環境に依存するため共有しずらいことなど、考慮して運用しなければならないのが現状です。