サムネがコーヒーの記事は書きかけです。

任意の年のよく雨が降る曜日を求める

今年は日曜日がよく雨降るな、去年は水曜日がよく雨が降ってたななどの直感を確かめるために、気象庁データをスクレイピングして、実際に任意の年の雨が多い曜日を可視化してみます。ついでに、降水量データを用いて簡単なデータ分析をしてみます。

データ分析の用意

はじめに、データ分析の際必要となる処理を行う関数を作成しておきます。

以下は、n年m月d日を曜日に変換するスクリプトです。

def get_day(year: int, month: int, date: int) -> str:
    japanese_days = [
        "月曜日",
        "火曜日",
        "水曜日",
        "木曜日",
        "金曜日",
        "土曜日",
        "日曜日",
    ]
    _, last_day = calendar.monthrange(year, month)

    weekdays = [
        (f"{year}年{month}月{day}日", japanese_days[calendar.weekday(year, month, day)])
        for day in range(1, last_day + 1)
    ]
    return {str(n + 1): (day, weekday) for n, (day, weekday) in enumerate(weekdays)}[
        str(date)
    ][1]


以下はrequestモジュールを用いて気象庁のデータベースに降水量情報を問い合わせる関数です。
データ参照元は以下のサイトになります。
https://www.data.jma.go.jp/stats/etrn/index.php

def get_precipitation_data(year: int, month: int) -> list]:
    url: str = (
        f"https://www.data.jma.go.jp/stats/etrn/view/daily_a1.php?prec_no=67&block_no=0683&year={year}&month={month}&day=&view="
    )
    content: bytes = requests.get(url).content
    sp: BS = BS(content, "html.parser")
    mtx_rows: list[BS] = sp.find_all("tr", class_="mtx")

    prec_data = [
        [cell.get_text(strip=True) for cell in row.find_all(["td", "th"])]
        for row in mtx_rows
    ]

    ## header1 = ['日', '降水量', '気温', '湿度', '風向・風速', '日照時間(h)', '雪']
    ## header2 =['合計(mm)', '最大1時間(mm)', '最大10分間(mm)', '平均(℃)', '最高(℃)', '最低(℃)', '平均(%)', '最小(%)', '平均風速(m/s)', '最大', '最大瞬間', '最多風向', '降雪の深さの合計(cm)', '最深積雪(cm)']
    return prec_data[3:]

>>>
['1', '6.5', '2.0', '1.0', '17.1', '21.0', '11.6', '87', '68', '1.0', '3.0', '南南西', '4.3', '南南西', '北東', '0.0', '///', '///']
['2', '38.0', '11.5', '3.0', '20.3', '24.6', '17.9', '91', '70', '1.6', '4.4', '北北西', '6.4', '北', '北北西', '0.0', '///', '///']
['3', '0.0', '0.0', '0.0', '19.7', '25.9', '12.2', '60', '29', '3.1', '6.4', '北北西', '11.7', '北', '北北西', '13.4', '///', '///']
['4', '0.0', '0.0', '0.0', '18.1', '25.4', '10.1', '71', '39', '1.8', '5.3', '西南西', '8.1', '西南西', '西', '5.8', '///', '///']
['5', '0.0', '0.0', '0.0', '19.0', '26.5', '12.5', '70', '32', '1.3', '3.6', '南', '5.0', '南', '西', '1.9', '///', '///']
['6', '7.5', '2.0', '1.0', '16.8', '19.1', '14.5', '89', '72', '1.4', '4.1', '南西', '6.6', '南南西', '西南西', '0.0', '///', '///']
['7', '0.0', '0.0', '0.0', '18.8', '26.3', '12.9', '83', '56', '1.3', '3.6', '西南西', '6.0', '南南東', '西北西', '6.7', '///', '///']
['8', '22.0', '6.0', '1.5', '17.2', '21.1', '14.5', '92', '71', '1.2', '5.1', '東北東', '7.0', '東北東', '西北西', '0.0', '///', '///']
['9', '0.0', '0.5', '0.0', '20.4', '26.6', '16.7', '83', '51', '1.5', '3.8', '南', '5.8', '南東', '西', '6.8', '///', '///']
['10', '1.5', '1.5', '0.5', '20.2', '25.8', '14.6', '81', '51', '1.6', '4.1', '南東', '6.4', '南東', '南', '5.4', '///', '///']
['11', '0.0', '1.5', '0.5', '21.3', '25.8', '18.1', '85', '62', '1.6', '4.4', '南東', '8.0', '南東', '西南西', '0.4', '///', '///']
['12', '0.0', '0.0', '0.0', '22.5', '27.5', '19.3', '84', '65', '1.4', '4.4', '南東', '7.2', '南東', '南南東', '2.8', '///', '///']
['13', '0.0', '0.0', '0.0', '23.0', '27.4', '19.7', '81', '63', '2.0', '4.5', '南南西', '7.1', '南', '西', '3.1', '///', '///']
['14', '12.0', '9.0', '7.0', '21.3', '24.7', '19.6', '90', '76', '1.1', '4.8', '西北西', '9.9', '西北西', '西北西', '0.0', '///', '///']
['15', '1.0', '1.0', '1.0', '20.4', '26.8', '16.3', '89', '59', '1.4', '6.2', '南西', '10.7', '南西', '北西', '2.6', '///', '///']
['16', '0.0', '0.0', '0.0', '21.3', '28.7', '14.5', '79', '47', '1.6', '4.6', '南', '7.0', '南東', '西', '9.5', '///', '///']
['17', '0.0', '0.0', '0.0', '22.7', '30.5', '15.7', '71', '34', '1.6', '4.7', '西南西', '8.2', '西南西', '西', '12.6', '///', '///']
['18', '0.0', '0.0', '0.0', '21.9', '28.7', '17.3', '76', '48', '1.2', '3.9', '南', '6.0', '南', '西', '3.7', '///', '///']
['19', '0.0', '0.0', '0.0', '23.9', '32.1', '15.8', '66', '33', '1.5', '4.6', '北北西', '9.2', '北西', '北', '13.7', '///', '///']
['20', '0.0', '0.0', '0.0', '22.8', '30.1', '16.0', '70', '43', '1.9', '4.6', '南', '7.4', '南', '西北西', '10.8', '///', '///']
['21', '9.5', '5.0', '1.5', '20.8', '22.8', '18.6', '91', '78', '1.2', '3.5', '東', '4.6', '東北東', '西北西', '0.0', '///', '///']
['22', '0.5', '0.5', '0.5', '20.9', '23.4', '19.3', '90', '80', '1.0 ]', '1.8 ]', '北北西', '2.7 ]', '北北西', '北 ]', '0.0', '///', '///']
['23', '0.0 )', '0.0 )', '0.0 )', '22.2 )', '27.7 )', '18.1 )', '82 )', '62 )', '2.2 ]', '4.0 ]', '西南西', '6.1 ]', '西', '西 ]', '3.8', '///', '///']
['24', '0.0', '0.0', '0.0', '22.3', '27.9', '17.2', '77', '52', '1.4', '3.6', '南南東', '6.0', '南東', '南', '6.8', '///', '///']
['25', '0.0', '0.0', '0.0', '23.1', '28.6', '17.4', '77', '55', '1.8', '4.8', '西南西', '8.7', '南南西', '西南西', '6.9', '///', '///']
['26', '5.0', '1.5', '0.5', '23.3', '26.7', '21.0', '91', '79', '1.3', '3.7', '西南西', '5.6', '西', '南西', '0.0', '///', '///']
['27', '0.0', '0.0', '0.0', '25.0', '29.6', '21.3', '83', '62', '1.8', '5.1', '西南西', '8.1', '西', '西南西', '2.1', '///', '///']
['28', '6.0', '5.5', '4.5', '24.0', '29.1', '21.2', '87', '64', '2.4', '5.8', '西南西', '9.6', '西', '西南西', '0.7', '///', '///']
['29', '6.0', '3.5', '1.5', '24.8', '29.0', '23.3', '89', '69', '2.3', '6.2', '南西', '9.6', '南西', '西南西', '1.9', '///', '///']
['30', '61.0', '17.0', '7.5', '23.4', '25.3', '22.0', '95', '88', '2.4', '5.3', '南南西', '9.6', '南南西', '南南西', '0.0', '///', '///']

データの取得

分析毎にデータベースに問い合わせを行うと気象庁のサーバーに負荷がかかるので、あらかじめ必要なデータを抽出してローカルに保存しておきます。

import time
import json

ret = {}
for year in range(2023, 2024):
    ret[year] = {}
    for month in range(1, 13):
        ret[year][month] = {}
        time.sleep(0.5)
        print(year, month)
        for i in get_precipitation_data(year, month):
            date = i[0]
            prec = i[1]
            ret[year][month][date] = prec
with open("data_2023.json", "w") as f:
    json.dump(ret, f, indent=4)

データの可視化

上記のJSONデータから、2023年全ての日付の曜日ごとの降水量を抽出します。

with open("data_2023.json", "r") as f:
    data = json.load(f)

days = {
    "月曜日": [],
    "火曜日": [],
    "水曜日": [],
    "木曜日": [],
    "金曜日": [],
    "土曜日": [],
    "日曜日": [],
}
for month in range(1, 13):
    for date in range(1, 32):
        try:
            day = get_day(2023, month, date)
            prec = float(
                data["2023"][str(month)][str(date)]
                .replace(")", "")
                .replace("(", "-")
                .replace("'", "")
            )
            if prec > 0:
                days[day].append(prec)
        except KeyError:
            pass
print(days)
>>>
{'月曜日': [0.5, 8.5, 10.5, 1.5, 11.5, 5.0, 24.5, 4.5, 31.0, 4.5, 3.0, 0.5, 0.5, 24.0], '火曜日': [3.0, 0.5, 1.0, 37.0, 20.5, 7.5, 0.5, 1.5, 1.0, 1.0, 5.5, 4.5, 0.5], '水曜日': [5.5, 6.0, 7.5, 26.5, 2.5, 12.0, 9.5, 6.0, 26.5, 0.5, 9.5, 5.0, 0.5, 0.5], '木曜日': [1.5, 1.0, 5.5, 26.5, 6.0, 6.5, 22.0, 1.0, 0.5, 6.0, 2.0, 0.5, 6.0, 10.0, 4.0, 3.5, 12.5, 5.0, 10.0], '金曜日': [15.5, 0.5, 7.0, 0.5, 2.0, 47.0, 12.0, 24.0, 38.0, 61.0, 9.0, 0.5, 0.5, 4.0, 0.5, 3.5, 9.0, 4.5], '土曜日': [1.0, 12.0, 8.0, 17.0, 4.5, 27.0, 28.0, 45.0, 8.5, 1.5, 80.0, 63.5, 4.5, 1.0, 3.0, 0.5], '日曜日': [3.5, 15.5, 14.0, 12.5, 4.0, 2.5, 92.0, 3.0, 81.5, 11.5, 0.5, 5.0, 0.5, 3.0]}

抽出したデータから、曜日ごとの1年間の合計降水量を可視化してみます。

降水量で見ると土曜日が一番高いことがわかります。

次に、降水頻度で見てみます。

with open("data_2023.json", "r") as f:
    data = json.load(f)

days = {
    "月曜日": 0,
    "火曜日": 0,
    "水曜日": 0,
    "木曜日": 0,
    "金曜日": 0,
    "土曜日": 0,
    "日曜日": 0,
}
for month in range(1, 13):
    for date in range(1, 32):
        try:
            day = get_day(2023, month, date)
            prec = float(
                data["2023"][str(month)][str(date)]
                .replace(")", "")
                .replace("(", "-")
                .replace("'", "")
            )
            if prec > 0:
                days[day] += 1
        except KeyError:
            pass

降水頻度で見ると木曜日が一番高いことがわかりました。

次に、1日ごとの降水量を可視化してみます。

このデータを元に、1LAG(日)ごとの自己相関を可視化してみます。


上図を見ると、ラグ1の自己相関が0.4付近であることから、ある日の降水量が高い場合、次の日も雨であることが多いことがわかります。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です