SIGNATE Quest③ 宿泊価格推定

#もくじ：回帰問題の処理手順

①欠損値の処理(①と②を繰り返す)
②基本的手順に沿ってデータの特徴を把握する
　　基本統計量
　　可視化
③特徴量生成
④重回帰モデルの作成と予測の実行
⑤予測結果の評価(RMSE)
⑥モデルの予測精度改善(⑤に戻る)

#欠損値の処理

![2020-08-24_23h38_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/677c37ac-cf73-fe66-d9a6-c0c0a623aeb1.png)

![2020-08-24_23h39_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/78fe6726-8d09-2e53-2ba5-60894e62944a.png)

![2020-08-24_23h39_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/41f6985c-3bd1-ed1f-5238-76ecc5717cdd.png)

![2020-08-24_23h41_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/a296fc77-0c67-c8af-5c31-51fbcf4d2496.png)

![2020-08-24_23h43_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/fae712dd-59d5-fa05-b850-20c13cd3fbe7.png)

![2020-08-24_23h44_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/259b86e5-2bbd-54e3-6466-1d0394555f7d.png)

![2020-08-24_23h45_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/a98e1381-8ff9-1d8b-7927-ca8216c5885a.png)

![2020-08-24_23h45_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/8806b95d-61bd-406b-ab79-361c093702ed.png)

![2020-08-24_23h46_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/a3732158-956f-6d2b-8d05-c97bff8f18ec.png)

![2020-08-24_23h46_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/54c59e0c-efc4-4189-5ce1-659670c5f2b8.png)

####重要な関数
　　**DataFrame.isnull().sum()**
　　**DataFrame.dropna()**
　　**DataFrame.fillna()**



#データ操作
```
# bedsがNaNになっているデータの抜き出し(SQLで言う select * where )
beds_nan_data = DataFrame[DataFrame['beds'].isnull()]

# bed_typeの種類ごとの件数を表示
print(beds_nan_data['bed_type'].value_counts())

# beds,bedrooms,bathroomsに欠損値を含むデータを削除
data = data.dropna(subset=['beds','bedrooms','bathrooms'])

# 変数mean_valにreview_scores_ratingの平均値を代入してください。
mean_val = data['review_scores_rating'].mean()

# review_scores_ratingの欠損値を平均値で補完してください。
data['review_scores_rating'] = data['review_scores_rating'].fillna(mean_val)
```

#データの可視化

![2020-08-25_23h14_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/3b2e40c2-13e2-dd2b-b480-db63b6460cdb.png)

![2020-08-25_23h15_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/9d006eec-9a19-0473-23db-fd9737fa4ff4.png)

![2020-08-26_08h29_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/a32152ef-88dc-33da-34d9-1b7cf595a036.png)

![2020-08-26_08h30_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/bd51f23b-4c86-5db8-4696-b1d9931c4c50.png)

![2020-08-26_08h31_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/f7796816-78d5-4a47-8a33-4bb655fdd7c0.png)

![2020-08-26_08h31_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/ef79c59f-c4e6-075e-e9b1-1d1510d1704c.png)

![2020-08-26_08h33_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/d3ab4cd6-a6bb-2eba-3b5b-03c8dd155c85.png)

![2020-08-26_08h44_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/885db293-7109-f48b-a68f-0e87e51dc270.png)

![2020-08-26_08h45_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/93cab3b0-7bb9-78c8-1045-9a1a75c3ca33.png)

![2020-08-26_08h46_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/58c7f9a8-fcb6-b8bb-9301-a3f8317eb768.png)

![2020-08-26_08h46_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/1826cbe0-8d00-4764-262e-b47c3e0c26c0.png)

####基本統計量

```
#要素の内容を表示
print(DataFrame['カラム名'].unique())
#要素の数を表示
print(DataFrame['カラム名'].nunique())
#重要:要素ごとの数を降順で表示
print(DataFrame['カラム名'].value_counts())

#2,4,7,7,10,12,13,17,20,22,30の統計量を表示する
#平均値、中央値、最大値などの値と最頻値を表示
s = pd.Series([2,4,7,7,10,12,13,17,20,22,30])
print(s.describe())
print(s.mode())
```

####ヒストグラム、棒グラフ
```
# 変数dataからy列のみを抜き出し、変数yに代入しましょう
y = data['y']
# ヒストグラムの可視化
y.plot.hist(title='宿泊価格')
# 可視化結果を表示する為に必要な関数
plt.show()

# value_counts()の結果を棒グラフで表示
v = data['カラム名'].value_counts()
v.plot.bar()
plt.show()
```

####外れ値の削除
```
# yが10以上のデータを抽出したい(10未満を削除したい)ので、条件はdata['y'] >= 10

# 削除前の行数を確認
before_rows = data.shape[0]
print(before_rows)

# 削除
data = data[data['y'] >= 10]

# 削除後の行数を確認
after_rows = data.shape[0]
print(after_rows)
```

####箱ひげ図の描画
```
# 箱ひげ図の描画
sns.boxplot(data=DataFrame, x='横カラム名', y='縦カラム名')

# 表示範囲を制限
plt.ylim(0,600)

plt.show()
```

####散布図の描画
```
DataFrame.plot.scatter(x='横カラム名', y='縦カラム名')
plt.show()
```

####複数の条件で抜き出す
```
# dataからbathroomsが0.0でyが1000ドル以上のデータを抜き出して、表示させてください。
# 複数条件を満たす場合は DataFrame[(条件) & (条件)]
data_tmp = data[(data['bathrooms']==0.0) & (data['y'] >= 1000)]
```

#特徴量の加工
![2020-08-26_14h04_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/d0e347bf-675e-501d-c950-2fa37d7cb27d.png)

![2020-08-26_14h05_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/76101cc7-4751-da9f-db79-6b9cdd15ff9b.png)

![2020-08-26_14h05_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/30bfae59-59cd-ab6a-488e-6e9bedb3db10.png)

![2020-08-26_14h06_38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/ece0bd92-743d-a588-789d-e5e4b3a74b68.png)

![2020-08-26_14h07_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/22a40edf-510a-58b2-a4a0-062f13723bf7.png)

![2020-08-26_14h07_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/67fbe671-f4a9-c2f5-0c7c-f36e11e27831.png)

#関数
![2020-08-26_15h12_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/890f8b8d-7a78-fcca-5fa6-5e5b406dfea9.png)

![2020-08-26_15h12_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/0f775cd6-3903-95d2-4478-a5d5ecd3c47a.png)

![2020-08-26_15h12_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/40828319-e24f-a609-40cd-7f665827e44e.png)

**自作関数だと関数を定義した後に関数を呼び出す必要があるが、lambda関数だと関数定義と呼び出しが1行でできる。**

![2020-08-26_15h13_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/e2dfbde2-621b-d360-8d88-8e1a97c96b9f.png)

![2020-08-26_15h13_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/8773a12e-6dd3-e9a2-afd7-2f9ee1198e67.png)

```
# property.csvを読み込んで変数dataに代入しましょう。
mydata = pd.read_csv('property.csv')

# cleaning_feeがt,fになっているので1,0に変換してください。
def change_tf(x):
    if x == 't':
        return 1
    elif x == 'f':
        return 0
mydata['cleaning_fee'] = mydata['cleaning_fee'].apply(change_tf)
```

#評価関数
![2020-08-26_17h14_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/3d75e8e7-a951-bc98-a0c8-5c8adf234e6a.png)

![2020-08-26_17h15_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/9f896cc9-c9b2-d7b9-c87c-0cf4a5b81662.png)

![2020-08-26_17h15_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/948353e9-183a-f009-2be3-2d463a0dead7.png)

![2020-08-26_17h16_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/d87de035-a115-c825-bd7d-5915bbaac5c1.png)

![2020-08-26_17h18_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/68e34658-a24b-ca15-27ce-ae5d2ffb968a.png)

![2020-08-26_17h18_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/2783beed-cdbe-6bf8-991c-752e182c05c7.png)

![2020-08-26_17h19_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/d793b032-9120-c9a3-c72b-c80dd8b93884.png)

##RMSEの計算方法
```
# ライブラリのインポート
import numpy as np
from sklearn.metrics import mean_squared_error as MSE

# 変数の準備
actual = [3,4,6,2,4,6,1]
pred = [4,2,6,5,3,2,3]

# MSEの算出
mse = MSE(actual,pred)
print(mse)

# RMSEの算出
rmse = np.sqrt(mse)
print(rmse)
```
**RMSEはscikit-learnに実装されていません。RMSEの平方根を取る前の値であるMSE(Mean Squared Error)は実装されています。MSEの平方根をとる部分を実装することでRMSEを算出しています。**

# 線形回帰モデル
![2020-08-26_17h32_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/e35b9ab0-a6c3-7b95-0db6-80e5e907c13b.png)

![2020-08-26_17h33_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/fe6b47aa-d78c-cd6a-475a-1d1145e64a93.png)

![2020-08-26_17h33_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/b3fb32cd-634c-97ae-4fdd-8c40ef10ba41.png)

```
# LinearRegressionをインポートしましょう。
from sklearn.linear_model import LinearRegression

# モデルの準備
lr = LinearRegression()

# モデルを学習
lr.fit(X_train, y_train)

# 偏回帰係数の表示
print(pd.DataFrame(lr.coef_, index=X_train.columns))

# 切片の表示
print(lr.coef_)

# X_trainに対して予測するように空欄を埋めてください。
y_pred_train = lr.predict(X_train)

# 予測結果の確認
print(y_pred_train)

# 結果を丸めて表示
chk = int(round(y_pred_train[1]))
```

###まとめ：説明変数、データ分割、モデル作成、モデル評価(RMSE)
```
# 予測に使用する説明変数、データ分割、モデル作成、モデル評価(RMSE)
select_columns = ['room_type','accommodates','bed_type','bathrooms','cleaning_fee']
dummy_data = pd.get_dummies(data[select_columns],drop_first=True)

X_train,X_test,y_train,y_test = train_test_split(dummy_data, data['y'], random_state = 1234)

lr = LinearRegression()
lr.fit(X_train, y_train)

y_pred_train = lr.predict(X_train)

# X_trainのRMSEを算出
rmse_train = np.sqrt(MSE(y_train, y_pred_train))

# 評価用に残しておいたX_testを使って予測
y_pred_test = lr.predict(X_test)

# X_testの予測に対するRMSEの算出
rmse_test = np.sqrt(MSE(y_test,y_pred_test))

# 学習および評価データに対するRMSEを表示
print(rmse_train)
print(rmse_test)
```

**testデータに対するRMSEが約131であることから、このモデルは評価用データに対しては、実際の宿泊価格に対して、平均して131ドル程度の誤差がある予測をしていることが分かります。**


####3つのモデルを作成し、統合した結果の線形回帰分析結果を表示する

```

select_columns = ['room_type','accommodates','bed_type','bathrooms','cleaning_fee']

data_entire = data[data['room_type'] == 'Entire home/apt']
data_private = data[data['room_type'] == 'Private room']
data_share = data[data['room_type'] == 'Shared room']
dummy_data_entire = pd.get_dummies(data_entire[select_columns], drop_first=True)
dummy_data_private = pd.get_dummies(data_private[select_columns],drop_first=True)
dummy_data_share = pd.get_dummies(data_share[select_columns], drop_first=True)

X_train_e,X_test_e,y_train_e,y_test_e = train_test_split(dummy_data_entire, data_entire['y'], random_state = 1234)
X_train_p,X_test_p,y_train_p,y_test_p = train_test_split(dummy_data_private, data_private['y'], random_state = 1234)
X_train_s,X_test_s,y_train_s,y_test_s = train_test_split(dummy_data_share, data_share['y'], random_state = 1234)

model_e = LinearRegression()
model_e.fit(X_train_e, y_train_e)
pred_e_train = model_e.predict(X_train_e)
pred_e_test = model_e.predict(X_test_e)

model_p = LinearRegression()
model_p.fit(X_train_p, y_train_p)
pred_p_train = model_p.predict(X_train_p)
pred_p_test = model_p.predict(X_test_p)

model_s = LinearRegression()
model_s.fit(X_train_s, y_train_s)
pred_s_train = model_s.predict(X_train_s)
pred_s_test = model_s.predict(X_test_s)

# pred_e_train, pred_p_train, pred_s_trainを1つの配列にして、pred_trainに代入してください。
pred_train = np.concatenate([pred_e_train, pred_p_train, pred_s_train])
# 実際の値であるy_train_e,y_train_p,y_train_sを1つの配列にして、answer_trainに代入してください。
answer_train = np.concatenate([y_train_e,y_train_p,y_train_s])
# pred_train,answer_trainから全訓練データの予測値のRMSEを求め、rmse_trainに代入してください。
rmse_train = np.sqrt(MSE(pred_train, answer_train))

# 同様に全テストデータの予測値のRMSEを求め、rmse_testに代入してください。
pred_test = np.concatenate([pred_e_test, pred_p_test, pred_s_test])
answer_test = np.concatenate([y_test_e,y_test_p,y_test_s])
rmse_test = np.sqrt(MSE(pred_test, answer_test))

print(rmse_train)
print(rmse_test)
```

以上