SIGNATE Quest④

#可視化

####ヒストグラムの使いどころ
数量変数の可視化にはヒストグラムが適している。
"性別"にデータが数値以外になっている場合、ヒストグラムだとデータの数値変換が必要となる。
棒グラフは数値変換が不要である為、この場合は棒グラフの方が適していると言える。

データの内容を数値項目とカテゴリ項目に分けている場合、数値項目の変数をヒストグラムにすると、それぞれの列ごとにヒストグラムを作成してくれる。(10列ある場合、一度に10個のヒストグラムを作ってくれる)

```
#ライブラリのimport
import pandas as pd
import matplotlib.pyplot as plt

#前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)

#データフレームの分離
col_categoric = ["Gender", "disease"]
df_numeric = df.drop(col_categoric, axis=1)
df_categoric = df[col_categoric]

#数量変数のヒストグラムを表示(※figsizeオプションはグラフのサイズを指定）
df_numeric.hist(figsize=(8, 6))

# グラフのラベルが重ならないようにレイアウトを自動調整
plt.tight_layout()
plt.show()
```
####結果
![2020-09-06_10h25_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/2a940f92-5706-ee62-37ef-07452c7d5f20.png)


####ヒストグラムを重ねて表示する
```
# ライブラリのimport
import pandas as pd
import matplotlib.pyplot as plt

# seabornライブラリをsnsという省略名でインポート
import seaborn as sns

# 前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)
col_categoric = ["Gender", "disease"]
df_numeric = df.drop(col_categoric, axis=1)
df_categoric = df[col_categoric]

# disease列とdf_numericを結合
df_tmp = pd.concat([df_categoric["disease"], df_numeric], axis=1)

# diseaseの値に応じた"Age"データの抽出
df_Age_non=df_tmp.query("disease==0")["Age"]
df_Age_diseased=df_tmp.query("disease==1")["Age"]

# 2つのデータフレームのヒストグラムを同時に表示
sns.distplot(df_Age_non)
sns.distplot(df_Age_diseased)
# 凡例の表示
plt.legend(labels=["non", "diseased"], loc='upper right')
plt.show()
```
![2020-09-06_10h47_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/3239c4ad-2325-84c8-bb7b-f4887615483e.png)



#データの抽出

データの抽出方法は主に2種類ある。

```
#データフレームの再帰代入
df_tmp[df_tmp["disease"] == 0]
#query関数を使う
df_tmp.query("disease == 0")
```

**↓ 重要：queryを使ったデータ抽出方法。複数条件の場合はqueryを推奨 ↓**

```
# diseaseの値に応じた"Age"データの抽出
df_Age_non=df_tmp.query("disease==0")["Age"]
df_Age_diseased=df_tmp.query("disease==1")["Age"]
```

![2020-09-06_10h47_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/0c4ca7a8-91c7-7ef0-f4f8-f274a6adb930.png)
![2020-09-06_10h47_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/e3c20362-53e6-8139-29a5-c341075872c2.png)

#corr()の結果をヒートマップで表示する

```
# ライブラリのimport
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)

# heatmapの表示
plt.figure(figsize=(10,8))
sns.heatmap(df.corr(), vmin=-1.0, vmax=1.0, annot=True, cmap='coolwarm', linewidths=0.1)
plt.show()
```
![2020-09-07_22h13_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/eac40eb6-3060-6032-6eaf-8cf9dfed75dc.png)

#ロジスティック回帰を使った疾患の予測

```
# ライブラリのimport
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, roc_curve

# 前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)
df["Gender"] = df["Gender"].apply(lambda x: 1 if x=="Male" else 0)

# 説明変数・目的変数の作成と分割
X = df.drop(["disease"], axis=1)
y = df["disease"]
X_train, X_test, y_train, y_test = train_test_split(X, y ,test_size=0.3, random_state=0)

# モデルの学習
lr = LogisticRegression()
lr.fit(X_train, y_train)

# モデルの予測（疾患あり(=1)に属する確率の算出）
y_pred_prob = lr.predict_proba(X_test)[:, 1]

# AUCスコアの算出
auc_score = ____(y_true=____, y_score=____)
print(auc_score)

# ROC曲線の要素（偽陽性率、真陽性率、閾値）の算出
fpr, tpr, thresholds = ____(y_true=____, y_score=____)

# ROC曲線の描画
plt.plot(fpr, tpr, label='roc curve (area = %0.3f)' % auc_score)
plt.plot([0, 1], [0, 1], linestyle=':', label='random')
plt.plot([0, 0, 1], [0, 1, 1], linestyle=':', label='ideal')
plt.legend()
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.show()
```

#ビニングした列の作成、ダミー変数化して元データに横連結。生成した特徴量を使って再度モデリング。

```
# ライブラリのインポート
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, roc_curve
import pandas as pd
import matplotlib.pyplot as plt

# 前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)
df["Gender"] = df["Gender"].apply(lambda x: 1 if x=="Male" else 0)
X = df.drop(["disease"], axis=1)
y = df["disease"]

# binの境界値を指定
bins_T_Bil = [0, 0.5, 1.0, 100]

# T_Bil列を分割し、0始まりの連番でラベル化した結果を、X_cutに格納する
X_cut, bin_indice = pd.cut(X["T_Bil"], bins=bins_T_Bil, retbins=True, labels=False)

# bin分割した結果をダミー変数化 (prefix=X_Cut.nameは、列名の接頭語を指定している)
X_dummies = pd.get_dummies(X_cut, prefix=X_cut.name)

# 元の説明変数のデータフレーム(X)と、ダミー変数化の結果(X_dummies)を横連結
X_binned = pd.concat([X, X_dummies], axis=1)

# 学習用・評価用データの分割（元の説明変数Xの代わりに、bin分割したX_binnedを使う）
X_train, X_test, y_train, y_test = train_test_split(X_binned, y, test_size=0.3, random_state=0)

# モデルの学習・予測
model = LogisticRegression()
model.fit(X_train, y_train)
y_pred = model.predict_proba(X_test)[:, 1]

# ROC曲線の描画（偽陽性率、真陽性率、閾値の算出）
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=y_pred)
plt.plot(fpr, tpr, label='roc curve')
plt.plot([0, 1], [0, 1], linestyle=':', label='random')
plt.plot([0, 0, 1], [0, 1, 1], linestyle=':', label='ideal')
plt.legend()
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.show()

# AUCスコアの算出
auc_score = roc_auc_score(y_true=y_test, y_score=y_pred)
print("AUC:", auc_score)
```


#多項式・交互作用特徴量の生成

```
# ライブラリのimport
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix
from sklearn.metrics import roc_curve, auc, roc_auc_score
from sklearn.preprocessing import PolynomialFeatures

# 前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)
df["Gender"] = df["Gender"].apply(lambda x: 1 if x=="Male" else 0)
X = df.drop(["disease"], axis=1)
y = df["disease"]

# Gender列を除外（数量変数のデータに絞る）
X_target = X.drop(["Gender"], axis=1)

# 多項式・交互作用特徴量の生成
polynomial = PolynomialFeatures(degree=2, include_bias=False)
polynomial_arr = polynomial.fit_transform(X_target)

# polynomial_arrのデータフレーム化 （※カラムはshape[1]でpolynomial_arrの列数分だけ出力）
X_polynomial = pd.DataFrame(polynomial_arr, columns=["poly" + str(x) for x in range(polynomial_arr.shape[1])])

# 生成した多項式・交互作用特徴量の表示
print(X_polynomial.shape)
print(X_polynomial.head())
```

#特徴量選択

```
# ライブラリのimport
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.feature_selection import SelectFromModel

# 前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)
df["Gender"] = df["Gender"].apply(lambda x: 1 if x=="Male" else 0)
X = df.drop(["disease"], axis=1)
y = df["disease"]
X_target = X.drop(["Gender"], axis=1)

# 多項式・交互作用特徴量の生成
polynomial = PolynomialFeatures(degree=2, include_bias=False)
polynomial_arr = polynomial.fit_transform(X_target)
X_polynomial = pd.DataFrame(polynomial_arr, columns=["poly" + str(x) for x in range(polynomial_arr.shape[1])])

# 組み込み法のモデル、閾値の指定
fs_model = LogisticRegression(penalty='l1', random_state=0)
# 閾値の指定
fs_threshold = "mean"
# 組み込み法モデルの初期化
selector = SelectFromModel(fs_model, threshold=fs_threshold)

# 特徴量選択の実行
selector.fit(X_polynomial, y)
mask = selector.get_support()

# 選択された特徴量だけのサンプル取得
X_polynomial_masked = X_polynomial.loc[:, mask]

print("選択された特徴量の表示（最初の5行）")
print(X_polynomial_masked.head())
print("選択された特徴量の数の確認")
print(X_polynomial_masked.shape)

```

#まとめ

```
# ライブラリのimport
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score, roc_curve
from sklearn.preprocessing import PolynomialFeatures
from sklearn.feature_selection import SelectFromModel

# 前処理
df = pd.read_csv('dataset.csv')
df["AG_ratio"].fillna(df["Alb"] / (df["TP"] - df["Alb"]), inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)
df["Gender"] = df["Gender"].apply(lambda x: 1 if x=="Male" else 0)
X = df.drop(["disease"], axis=1)
y = df["disease"]
X_target = X.drop(["Gender"], axis=1)

# 多項式・交互作用特徴量
polynomial = PolynomialFeatures(degree=2, include_bias=False)
polynomial_arr = polynomial.fit_transform(X_target)
X_polynomial = pd.DataFrame(polynomial_arr, columns=["poly" + str(x) for x in range(polynomial_arr.shape[1])])

# 組み込み法のモデル、閾値の指定
fs_model = LogisticRegression(penalty='l1', random_state=0)
fs_threshold = "mean"
# 組み込み法モデルの初期化
selector = SelectFromModel(fs_model, threshold=fs_threshold)

# 特徴量選択の実行
selector.fit(X_polynomial, y)
mask = selector.get_support()

# 選択された特徴量だけのサンプル取得
X_polynomial_masked = X_polynomial.loc[:, mask]

# 学習用・評価用データの分割（元の説明変数Xの代わりに、特徴量選択後のX_polynomial_maskedを使う）
X_train, X_test, y_train, y_test = train_test_split(X_polynomial_masked, y, test_size=0.3, random_state=0)

# モデルの学習・予測
model = LogisticRegression()
model.fit(X_train, y_train)
y_pred = model.predict_proba(X_test)[:, 1]

# ROC曲線の描画（偽陽性率、真陽性率、閾値の算出）
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=y_pred)
plt.plot(fpr, tpr, label='roc curve')
plt.plot([0, 1], [0, 1], linestyle=':', label='random')
plt.plot([0, 0, 1], [0, 1, 1], linestyle=':', label='ideal')
plt.legend()
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.show()

# AUCスコアの算出
auc_score = roc_auc_score(y_true=y_test, y_score=y_pred)
print("AUC:", auc_score)
```