search
LoginSignup
3

More than 1 year has passed since last update.

posted at

updated at

気象データの細かすぎる天気概況をなんとかまとめてみる

はじめに

この記事は スタンバイ Advent Calendar 2021 の15日目の記事です。
昨日の記事は @Nisi さんの【空冷自作PC】Ryzen7 5700G + ASRock DeskMini X300をノクチュア NH-P1でファンレスにした話でした。

概要

気象庁では、全国の観測点で記録した過去の気象データを公開しています。
一度に入手可能なデータ量に制限はありますが、
ユーザー登録無しで全国のアメダスのデータが無償で使えるのはとても素晴らしいです。

しかし、天気概況(晴、快晴、雨、大雨など)の種類が非常に細かく
(2020年東京の6時〜18時の気象概況では年間58種類使われている)
例えば、晴、雨、その中間の3分類程度で売上を比較したい、といった用途にはいささか不便です。
そこで、本記事では、気圧等の数値データに基づいて、一日の天気概況表現を再分類する方法を検討しました。

Contents

  • データの入手
  • データの概要
  • データの加工

データの入手

過去の気象データは無料で入手出来ます。以下のようなフォームが用意されているので、

  • 地点
  • 項目(気温、気圧など)
  • 期間
  • 表示オプション

を選択し、CSVファイルをダウンロードでデータ入手完了です。

image.png

なお、本記事では、以下の条件で取得したデータを使用します

  • 地点:東京
  • 項目:日平均気温、最高気温、最低気温、降水量の日合計、日照時間、日最深積雪、日平均風速、日平均現地気圧、日平均相対湿度、天気概況(昼:06時~18時)
  • 期間: 2020年1月1日〜2020年12月31日

ファイルの文字コードがShiftJISなので、必要に応じて文字コードを変換して下さい。

データの概要

早速、Pandasデータフレームに読み込んでみます。

# 必要なライブラリのインポート
import pandas as pd

# データの読み込み
df_weather = pd.read_csv('path/do/datadir/data.csv')
df_head() 

image.png

2020年はうるう年なので366行、問題なくデータを読み込めています。

次に、天気概況の分類をみてみます。

df_weather['天気概況(昼:06時〜18時)'].unique()

array(['晴', '晴一時曇', '快晴', '曇時々晴', '晴後一時曇', '曇後雨', '曇一時雨', '曇後晴', '曇後一時雨',
       '雨一時晴', '曇', '雨時々みぞれ一時雪', '曇後一時晴', '雨', '雨後曇', '晴一時雨', '晴時々曇',
       '薄曇時々晴', '薄曇後一時晴', '曇一時雨後晴', '薄曇', '雨時々曇', '晴後薄曇', '晴後一時薄曇',
       '曇時々晴後一時雨', '曇時々雨', '曇一時晴', '晴一時薄曇', '晴後一時雨', '雨後雪時々みぞれ',
       '曇一時雨後時々晴', '雨時々雪後一時曇、みぞれを伴う', '曇後雨一時晴', '晴後曇', '晴後時々曇', '大雨',
       '薄曇一時晴', '晴後曇時々雨', '晴時々薄曇', '曇後一時雨、雷を伴う', '曇時々雨、雷を伴う', '雨一時曇',
       '曇時々雨後晴', '曇時々晴一時雨、雷を伴う', '曇、雷を伴う', '曇一時雨後一時晴', '雨後時々曇', '曇時々雨一時晴',
       '曇後時々雨', '晴後曇一時雨、雷を伴う', '晴後時々曇一時雨、雷を伴う', '晴、雷を伴う', '曇時々大雨、雷を伴う',
       '晴時々曇一時雨', '曇時々雨一時晴、雷を伴う', '曇時々晴一時雨', '曇一時晴後雨', '曇後時々晴'],
      dtype=object)

「時々」、「一時」等と組み合わさって、こんな分類になるのね。

種類の数は

len(df_weather['天気概況(昼:06時〜18時)'].unique())
58

58種類も!! 細かすぎる、、、。

天気予報でよく出てくる「時々」と「一時」の定義について 時々: 断続的かつその時間が予報期間の1/2未満の場合 一時: 連続的かつその時間が予報期間の1/4未満の場合

データの加工

いよいよ天気概況を再分類します。
今回は、雨、晴、その中間の3つ程度に再分類したいと思います。
この程度の分類であれば、以下の予想をもとに、再分類を進めれそう(な気がします)。

  • 天候を左右するのは、気圧と湿度、風速ではないか
  • 似たような天気のときは、似たような値の組み合わせになるはず

似たようなものの分類、そう、クラスター分析の出番ですね。

クラスター分析 (Try1)

今回は、k-means法を使います。分析コードは以下の通り。

# 必要なライブラリを読み込む
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# クラスター分析に使用するカラムだけ抜き出す
df_analytics = df_weather[['平均現地気圧(hPa)','平均湿度(%)','平均風速(m/s)']]

# パラメータ間のオーダーをあわせるために値を標準化する
sc = StandardScalar()
df_analytics_std = sc.transform(df_analytics)

# k-means法によるクラスタ分析
kmeans = KMeans(init='random', n_clusters=3, random_state=0)
kmeans.fit(df_analytics_std)
labels = pd.Series(kmeans.labels_, name='cluster_number')

# 各クラスタのメンバー数を確認
print(labels.value_counts(sort=False))
1    136
2    168
0     62
Name: cluster_number, dtype: int64

# クラスター番号を結合
df_weather_lbl = pd.concat([df_weather, labels], axis=1)

各クラスターの天気概況(昼:06時〜18時)で使われている表現を見てみます。

# クラスター番号0
df_weather_class0 = df_weather_lbl[df_weather_lbl['cluster_number'] == 0]['天気概況(昼:06時〜18時)'].unique()
df_weather_class0

array(['晴後一時曇', '晴', '快晴', '曇時々晴後一時雨', '晴一時曇', '晴後一時雨', '薄曇時々晴', '曇',
       '曇時々雨', '晴一時薄曇', '晴時々薄曇', '薄曇', '雨一時曇', '曇後雨', '曇後晴', '雨時々曇',
       '晴時々曇一時雨', '曇時々雨、雷を伴う', '曇一時晴', '曇一時雨'], dtype=object)

# クラスター番号1
df_weather_class1 = df_weather_lbl[df_weather_lbl['cluster_number'] == 1]['天気概況(昼:06時〜18時)'].unique()
df_weather_class1

array(['晴', '晴一時曇', '快晴', '曇時々晴', '晴後一時曇', '曇後雨', '曇後晴', '曇', '曇後一時晴',
       '雨', '雨後曇', '晴時々曇', '薄曇時々晴', '薄曇後一時晴', '曇一時雨後晴', '曇後一時雨', '薄曇',
       '晴後薄曇', '晴後一時薄曇', '曇一時晴', '晴一時薄曇', '曇時々雨', '曇一時雨後時々晴', '晴後曇',
       '晴後時々曇', '薄曇一時晴', '曇一時晴後雨', '曇後時々晴', '雨後時々曇', '曇一時雨'], dtype=object)

# クラスター番号2
df_weather_class2 = df_weather_lbl[df_weather_lbl['cluster_number'] == 2]['天気概況(昼:06時〜18時)'].unique()
df_weather_class2

array(['曇一時雨', '曇後一時雨', '快晴', '雨一時晴', '雨時々みぞれ一時雪', '雨', '晴一時雨', '晴',
       '雨時々曇', '曇後晴', '曇時々雨', '曇一時晴', '雨後雪時々みぞれ', '晴後一時曇',
       '雨時々雪後一時曇、みぞれを伴う', '曇後雨一時晴', '大雨', '曇', '晴後曇時々雨', '曇後雨',
       '曇後一時雨、雷を伴う', '雨後曇', '曇時々晴', '曇時々雨、雷を伴う', '晴時々曇', '曇時々雨後晴', '晴一時曇',
       '薄曇', '曇時々晴一時雨、雷を伴う', '曇後一時晴', '薄曇時々晴', '曇、雷を伴う', '曇一時雨後一時晴',
       '雨一時曇', '雨後時々曇', '曇時々雨一時晴', '曇後時々雨', '晴後曇一時雨、雷を伴う',
       '晴後時々曇一時雨、雷を伴う', '晴、雷を伴う', '晴時々薄曇', '曇時々大雨、雷を伴う', '曇時々雨一時晴、雷を伴う',
       '晴後一時薄曇', '曇時々晴一時雨', '曇時々晴後一時雨', '晴後薄曇'], dtype=object)

ぱっと見た感じ、各クラスターがどのような天気概況の集団なのか、良くわからないです、、、。
ここで、分類性能を簡易的に評価するため、クラスター間の重複の数を数えてみましょう。

# 重複個数を確認
# 3クラスター重複
len(set(df_weather_class0).intersection(set(df_weather_class1), set(df_weather_class2)))
12

# クラスター0,1重複
len(set(df_weather_class0).intersection(set(df_weather_class1)))
13

# クラスター1,2重複
len(set(df_weather_class1).intersection(set(df_weather_class2)))
21

# クラスター2,0重複
len(set(df_weather_class2).intersection(set(df_weather_class0)))
17

どのクラスターも半分以上他のクラスターと重複しており、うまく分類出来ているとは言い難いです。
改良の余地がありそうです。

クラスター分析 (Try2)

気圧、湿度、風速の値だけで分類が難しい、であれば、パラメータを増やしてみることにします。
試しに、降水量の合計、日照時間を加えてみます。

# クラスター分析に使用するカラムだけ抜き出す
df_analytics = df_weather[['降水量の合計(mm)','日照時間(時間)','平均現地気圧(hPa)','平均湿度(%)','平均風速(m/s)']]

# 先程と同様

# 各クラスタのメンバー数を確認
print(labels.value_counts(sort=False))
0    181
1    149
2     36
Name: cluster_number, dtype: int64

再び、各クラスターの天気概況(昼:06時〜18時)で使われている表現を見てみます。

# クラスター番号0
df_weather_class0 = df_weather_lbl[df_weather_lbl['cluster_number'] == 0]['天気概況(昼:06時〜18時)'].unique()
df_weather_class0

array(['晴', '晴一時曇', '快晴', '曇時々晴', '晴後一時曇', '曇', '晴時々曇', '薄曇時々晴', '薄曇後一時晴',
       '曇一時雨後晴', '晴後薄曇', '薄曇', '晴後一時薄曇', '曇時々晴後一時雨', '曇一時晴', '晴一時薄曇',
       '晴後一時雨', '晴後曇', '晴後時々曇', '薄曇一時晴', '晴時々薄曇', '曇後晴', '晴、雷を伴う',
       '曇後一時晴', '晴一時雨', '曇後時々晴'], dtype=object)

# クラスター番号1
df_weather_class1 = df_weather_lbl[df_weather_lbl['cluster_number'] == 1]['天気概況(昼:06時〜18時)'].unique()
df_weather_class1

array(['曇後雨', '曇一時雨', '曇後晴', '曇後一時雨', '雨一時晴', '雨時々みぞれ一時雪', '曇後一時晴', '雨',
       '曇', '雨後曇', '薄曇', '雨時々曇', '曇時々雨', '曇一時晴', '曇一時雨後時々晴', '曇後雨一時晴',
       '晴後曇時々雨', '曇後一時雨、雷を伴う', '曇時々雨、雷を伴う', '曇時々雨後晴', '曇時々晴一時雨、雷を伴う',
       '曇、雷を伴う', '曇一時雨後一時晴', '晴一時曇', '曇後時々雨', '晴', '晴時々曇', '晴後曇一時雨、雷を伴う',
       '晴後時々曇一時雨、雷を伴う', '曇時々晴', '晴時々曇一時雨', '曇時々晴一時雨', '晴一時雨', '曇一時晴後雨',
       '曇時々晴後一時雨', '雨後時々曇', '晴後薄曇', '薄曇一時晴'], dtype=object)

# クラスター番号2
df_weather_class2 = df_weather_lbl[df_weather_lbl['cluster_number'] == 2]['天気概況(昼:06時〜18時)'].unique()
df_weather_class2

array(['雨', '晴一時雨', '雨時々曇', '雨後雪時々みぞれ', '曇時々雨', '雨時々雪後一時曇、みぞれを伴う', '大雨',
       '雨一時曇', '曇後雨', '雨後曇', '雨後時々曇', '曇時々雨一時晴', '曇時々大雨、雷を伴う',
       '曇時々雨一時晴、雷を伴う', '曇時々雨、雷を伴う', '曇'], dtype=object)

ぱっと見た感じ、おおよそ

  • クラスター番号0 : 晴
  • クラスター番号2 : 雨
  • クラスター番号1 : 中間

のように再分類出来ていそうです。
先程と同じように、クラスター間の重複をカウントしてみます。

# 重複個数を確認
# 3クラスター重複
len(set(df_weather_class0).intersection(set(df_weather_class1), set(df_weather_class2)))
2

# クラスター0,1重複
len(set(df_weather_class0).intersection(set(df_weather_class1)))
13

# クラスター1,2重複
len(set(df_weather_class1).intersection(set(df_weather_class2)))
9

# クラスター2,0重複
len(set(df_weather_class2).intersection(set(df_weather_class0)))
2

先程と比較してだいぶクラスター間の重複を減らせたのではないかと思います。

まとめ

  • 降水量合計、日照時間、平均現地気圧、平均風速、平均湿度をもとに、天気概況を3分類程度に分けられそう。
  • 他の地域でも試してみたい。(例えば、北海道など)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3