気象庁のデータを使って、雨が降るか予測します。
import numpy
import matplotlib
import sklearn
import pandas as pd
■データの特徴量は年月日、平均気温、降水量の合計、日照時間・・・。train_dfは2016/1/1-2019/1/1、test_dfには2019/1/1-2020/1/1。
train_df = pd.read_csv('train_tenki.csv', encoding='cp932')
test_df = pd.read_csv('test_tenki.csv', encoding='cp932')
combine = [train_df, test_df]
■雨が降ったかどうかが知りたいので、雨がふれば1、晴れれば0。テストデータには無くすのであとで削除する。
train_df['rain'] = train_df['降水量の合計(mm)'].apply(lambda x : 1 if x > 0 else 0)
■梅雨など時期によるところがあるので、年月日の月のみを抽出。
train_df['date'] = pd.to_datetime(train_df['年月日'])
train_df['Date'] = train_df['date'].dt.month
test_df['date'] = pd.to_datetime(test_df['年月日'])
test_df['Date'] = test_df['date'].dt.month
■余分なデータがたくさん付いてきたので、頑張って消してます。
train_df = train_df.drop(["date", "年月日","平均気温(℃).1", "平均気温(℃).2", "降水量の合計(mm).1", "降水量の合計(mm).2", "降水量の合計(mm).3","日照時間(時間).1", "日照時間(時間).2", "日照時間(時間).3", "平均風速(m/s).1", "平均風速(m/s).2", "平均蒸気圧(hPa).1", "平均蒸気圧(hPa).2", "平均現地気圧(hPa).1", "平均現地気圧(hPa).2", "平均海面気圧(hPa).1", "平均海面気圧(hPa).2", "平均湿度(%).1", "平均湿度(%).2", "平均雲量(10分比).1", "平均雲量(10分比).2", "降水量の合計(mm)" ], axis=1)
test_df = test_df.drop(["date", "年月日", "平均気温(℃).1", "平均気温(℃).2", "降水量の合計(mm).1", "降水量の合計(mm).2", "降水量の合計(mm).3","日照時間(時間).1", "日照時間(時間).2", "日照時間(時間).3", "平均風速(m/s).1", "平均風速(m/s).2", "平均蒸気圧(hPa).1", "平均蒸気圧(hPa).2", "平均現地気圧(hPa).1", "平均現地気圧(hPa).2", "平均海面気圧(hPa).1", "平均海面気圧(hPa).2", "平均湿度(%).1", "平均湿度(%).2", "平均雲量(10分比).1", "平均雲量(10分比).2", "降水量の合計(mm)" ], axis=1)
■余分なデータを消した後、下記特徴量と雨が降ったかどうかのヒストグラムと相関(下記分割)を見たところ、関係なさそうなのを削除。削除するのは平均気温、平均風速、平均蒸気圧。
train_df = train_df.drop(["平均気温(℃)", "平均風速(m/s)", "平均蒸気圧(hPa)"], axis=1)
test_df = test_df.drop(["平均気温(℃)", "平均風速(m/s)", "平均蒸気圧(hPa)"], axis=1)
■日照時間を分割。日照時間が短いほど雨になることがわかる。
train_df['日照時間'] = pd.qcut(train_df['日照時間(時間)'], 4)
train_df[['日照時間', 'rain']].groupby(['日照時間'], as_index=False).mean().sort_values(by='日照時間', ascending=True)
for dataset in combine:
dataset.loc[ dataset['日照時間(時間)'] <= 1.1, '日照時間(時間)'] = 0
dataset.loc[(dataset['日照時間(時間)'] > 1.1) & (dataset['日照時間(時間)'] <= 5.8), '日照時間(時間)'] = 1
dataset.loc[(dataset['日照時間(時間)'] > 5.8) & (dataset['日照時間(時間)'] <= 9.0), '日照時間(時間)'] = 2
dataset.loc[(dataset['日照時間(時間)'] > 9.0) ,'日照時間(時間)'] = 3
dataset['日照時間(時間)'] = dataset['日照時間(時間)'].astype(int)
train_df = train_df.drop(['日照時間'], axis=1)
combine = [train_df, test_df]
■湿度を分割。湿度が高いほど雨になることがわかる。
train_df['平均湿度'] = pd.qcut(train_df['平均湿度(%)'], 5)
train_df[['平均湿度', 'rain']].groupby(['平均湿度'], as_index=False).mean().sort_values(by='平均湿度', ascending=True)
for dataset in combine:
dataset.loc[ dataset['平均湿度(%)'] <= 54.0, '平均湿度(%)'] = 0
dataset.loc[(dataset['平均湿度(%)'] > 54.0) & (dataset['平均湿度(%)'] <= 65.0), '平均湿度(%)'] = 1
dataset.loc[(dataset['平均湿度(%)'] > 65.0) & (dataset['平均湿度(%)'] <= 75.0), '平均湿度(%)'] = 2
dataset.loc[(dataset['平均湿度(%)'] > 75.0) & (dataset['平均湿度(%)'] <= 84.0), '平均湿度(%)'] = 3
dataset.loc[(dataset['平均湿度(%)'] > 84.0) ,'平均湿度(%)'] = 4
dataset['平均湿度(%)'] = dataset['平均湿度(%)'].astype(int)
train_df = train_df.drop(['平均湿度'], axis=1)
combine = [train_df, test_df]
■平均現地気圧を分割。気圧は低い方が雨になる。
train_df['平均現地気圧'] = pd.qcut(train_df['平均現地気圧(hPa)'], 5)
train_df[['平均現地気圧', 'rain']].groupby(['平均現地気圧'], as_index=False).mean().sort_values(by='平均現地気圧', ascending=True)
combine = [train_df, test_df]
for dataset in combine:
dataset.loc[ dataset['平均現地気圧(hPa)'] <= 1005.1, '平均現地気圧(hPa)'] = 0
dataset.loc[(dataset['平均現地気圧(hPa)'] > 1005.1) & (dataset['平均現地気圧(hPa)'] <= 1009.5), '平均現地気圧(hPa)'] = 1
dataset.loc[(dataset['平均現地気圧(hPa)'] > 1009.5) & (dataset['平均現地気圧(hPa)'] <= 1012.9), '平均現地気圧(hPa)'] = 2
dataset.loc[(dataset['平均現地気圧(hPa)'] > 1012.9) & (dataset['平均現地気圧(hPa)'] <= 1016.9), '平均現地気圧(hPa)'] = 3
dataset.loc[(dataset['平均現地気圧(hPa)'] > 1016.9) ,'平均現地気圧(hPa)'] = 4
dataset['平均現地気圧(hPa)'] = dataset['平均現地気圧(hPa)'].astype(int)
train_df = train_df.drop(['平均現地気圧'], axis=1)
combine = [train_df, test_df]
■平均海面気圧を分割。気圧が低い方が雨になる。
train_df['平均海面気圧'] = pd.qcut(train_df['平均海面気圧(hPa)'], 5)
train_df[['平均海面気圧', 'rain']].groupby(['平均海面気圧'], as_index=False).mean().sort_values(by='平均海面気圧', ascending=True)
combine = [train_df, test_df]
for dataset in combine:
dataset.loc[ dataset['平均海面気圧(hPa)'] <= 1005.1, '平均海面気圧(hPa)'] = 0
dataset.loc[(dataset['平均海面気圧(hPa)'] > 1005.1) & (dataset['平均海面気圧(hPa)'] <= 1009.5), '平均海面気圧(hPa)'] = 1
dataset.loc[(dataset['平均海面気圧(hPa)'] > 1009.5) & (dataset['平均海面気圧(hPa)'] <= 1012.9), '平均海面気圧(hPa)'] = 2
dataset.loc[(dataset['平均海面気圧(hPa)'] > 1012.9) & (dataset['平均海面気圧(hPa)'] <= 1016.9), '平均海面気圧(hPa)'] = 3
dataset.loc[(dataset['平均海面気圧(hPa)'] > 1016.9) ,'平均海面気圧(hPa)'] = 4
dataset['平均海面気圧(hPa)'] = dataset['平均海面気圧(hPa)'].astype(int)
train_df = train_df.drop(['平均海面気圧'], axis=1)
combine = [train_df, test_df]
■平均雲量を分割。雲が多い方が雨になる。
train_df['平均雲量'] = pd.qcut(train_df['平均雲量(10分比)'], 3,duplicates='drop')
train_df[['平均雲量', 'rain']].groupby(['平均雲量'], as_index=False).mean().sort_values(by='平均雲量', ascending=True)
combine = [train_df, test_df]
for dataset in combine:
dataset.loc[ dataset['平均雲量(10分比)'] <= 5.8, '平均雲量(10分比)'] = 0
dataset.loc[(dataset['平均雲量(10分比)'] > 5.8) & (dataset['平均雲量(10分比)'] <= 9.5), '平均雲量(10分比)'] = 1
dataset.loc[(dataset['平均雲量(10分比)'] > 9.5) ,'平均雲量(10分比)'] = 2
dataset['平均雲量(10分比)'] = dataset['平均雲量(10分比)'].astype(int)
train_df = train_df.drop(['平均雲量'], axis=1)
combine = [train_df, test_df]
機械学習
from sklearn.ensemble import RandomForestClassifier
X_train = train_df.drop("rain", axis=1)
Y_train = train_df["rain"]
X_test = test_df
random_forest = RandomForestClassifier(n_estimators=100)
random_forest.fit(X_train, Y_train)
■モデルの精度は99.45。
Y_pred = random_forest.predict(X_test)
random_forest.score(X_train, Y_train)
acc_random_forest = round(random_forest.score(X_train, Y_train) * 100, 2)
■答えを保存して、実際のデータと比較。
submission_tenki = pd.DataFrame({
"Date": test_df["Date"],
"rain": Y_pred
})
submission_tenki.to_csv('./8010_titanic_data/submission_tenki.csv', index=False)
結果
正解率は79.3%。月と湿度と日照時間さえわかれば当たるかも。
上記で出てこなかった相関やヒストグラムなど
■年月日について
・8月は積乱雲が、5月-7月は梅雨。この時に雨が降る率は多いのでは??と思いきや雨が降る回数は9月が多かった。なぜか。
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
train_df["Date"].hist(bins=12)
plt.show()
train_df["Date"].hist(by=train_df["rain"])
plt.show()
■平均湿度
・湿度が高い時ほど雨。
train_df["平均湿度(%)"].hist(bins=20)
plt.show()
train_df["平均湿度(%)"].hist(by=train_df["rain"])
plt.show()
■平均気温
・ヒストグラムでは気温が高い方が雨が降りやすくなっているけど、相関みるとそうでもないと判断した。
■蒸気圧
・相関みてもあまり関係ないと判断。雨が降る仕組みを見ると影響ありそうだけど。
■現地気圧
・ヒストグラム上だと雨降った時と降ってないときの違いがないと思った。けど相関を見ると低いと雨が降りやすい。
■海面気圧
・ヒストグラム上だと雨降った時と降ってないときの違いがないと思った。けど相関を見ると低いと雨が降りやすい。
あとがき
■予想〜結果
今回、特徴量としたのは年月日、平均気温、日照時間、平均風速、平均蒸気圧、平均現地気圧、平均海面気圧、平均湿度、平均雲量。梅雨の時期があるように、年月日は影響がありそう。風速も、周囲の気圧差などで発生するものなので、期待。各気圧も低気圧だと天気が悪いということで期待。
ということで各特徴量とrainとの相関をみてみたところ、風速が雨にはあまり関係していなかった。暴風雨っていう言葉があるから雨と風速はセットだと思っていたが違ったよう。気圧は低いと雨になるようなので、雨の日に頭痛がしたり体調が悪くなるのは気圧が低いせいだ、というのもあながち間違いではないかも。日照時間と雲量は同じようなものなのか、二つともrainと相関があった。日照時間は短い時、雲量は多い時。今度は、雲があるから雨が降るのか、曇りの日にどれだけ雨は降りやすいのか、を調べるもの面白いかも。
ここで、雲ができて雨が降るまでを調べてみた。雲は水。水は空気中の水蒸気から得られる。水蒸気は空気中にあり、気温が高い方がより多く含む。その空気が各種上昇気流により上空に運ばれ、冷やされると雲になる。
雲の中の粒同士がぶつかり合い、水滴になる。そうすると上昇気流に逆らい地上へ落下。
今回の結果と比較してみると、気温が高いことは重要だが、今回は省いた。24度あたりが一番相関が強いが、他の特徴量と比べると弱いと思ったため。気温は重要だけど当日の気温が、ってわけではないのかなぁ。上昇気流はいろいろ種類があるけど、低気圧によるものもあるから、低気圧は雨の降る一つの要因で正しそう。
■今後の改善
特徴量同士を組み合わせたりしていないので、分析に対しての理解が必要。よくわかっていないので。あとは、型にはめただけなので、自分で使えるようになってからより良い改善点が出るし、なかなか楽しかったので引き続き勉強。