0
3

More than 1 year has passed since last update.

pandas x スクレイピングで時系列データ分析を試す

Last updated at Posted at 2022-08-23

今年の夏熱くない?

いつも私はエアコンなし・扇風機一本で夏を乗り切る男なのですが、
今年は暑さに耐え切れずエアコンを使用しています。
今年の夏の暑さが異常なのか、年を取って体力が落ちたのか、調査をしたいと思います。

調査方法

7月から8月までの平均気温と平均湿度を年ごとに折れ線グラフでプロットします。
データは気象庁のデータをスクレイピングすることで取得します。

モジュールインポート

import datetime
# データ分析
import pandas as pd
import numpy as np
# スクレイピング
import requests
from bs4 import BeautifulSoup
# 可視化
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns

分析用dataframeの作成

分析対象日のdatetimeindexを作成する

index = pd.date_range(start="2022-07-01", end="2022-08-31")
for i in range(2):
    # 一年分ずらす
    y_delta = index - pd.DateOffset(years=1)
    index   = index.union(y_delta)
index

結果

output_1.PNG

indexの結合にはunionメソッドを使うらしい。また新しいものに対して古いものを結合したのに、
結合後は自動的に時系列に並び変えてくれた。すごい。

作成したindexを基にdataframeを作成する

df = pd.DataFrame(index=index)

df["temp."] = np.nan
df["hum"]   = np.nan
df

結果

output_2.PNG

気象庁のデータをスクレイピングする

スクレイピング元

以下のようなページからデータを取得する。
年と月を基準にurlを更新すれば、その年月について日毎のデータが表に表示される。

気象庁.PNG

年と月を基準にグループ化する

後述のスクレイピングのループのiteratorとするために、
年月単位でグルーピングしたindexを取得する。
mean処理は特に意味はないが、何らかの処理を行わないとdataframeになってくれないので、やむを得ず実行。

hoge = df.groupby(by=[df.index.year, df.index.month]).mean()
hoge.index

結果

output_3.PNG

気象庁のデータをスクレイピングする

url更新→テーブルデータ取得→所望の行と列からデータを抜いてdfに格納

for Y, m in hoge.index:
    # urlを更新
    url = f"https://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?prec_no=44&block_no=47662&year={Y}&month={m}&day=&view="
    # htmlのtable要素を取得
    r     = requests.get(url)
    soup  = BeautifulSoup(r.text)
    table = soup.find("table", { "class" : "data2_s" })
    # 
    for iter, tr in enumerate(table.findAll("tr")):

        # 最初の四行は処理を行わない
        if iter <= 3:
            continue
        # 1列目と7列目と10列目の値を取得
        tds   = tr.findAll("td")
        d     = int(tds[0].string)
        try:
            _temp = float(tds[6].string)
            hum   = float(tds[9].string)
        except:
            _temp, hum = [np.nan, np.nan]
        # dfに格納
        df.loc[pd.to_datetime(datetime.datetime(Y, m, d)), "temp.":"hum"] = [_temp, hum]
df

結果

output_4.PNG

データを可視化する

分析用の列を追加。

seabornで可視化を行う。
今回は月日毎の温度と気温の変化を年ごとに比べたいので、以下の様に列を追加。

df["m/d"] = [timestamp.strftime(r"%m/%d") for timestamp in df.index]
df["Y"]   = df.index.year
df

結果

output_5.PNG

グラフで可視化

平均気温について

sns.set_style("whitegrid")
# figure定義
fig, ax = plt.subplots(figsize=(12.8, 7.2), dpi=100)
# plot
sns.lineplot(data=df, x="m/d", y="temp.", hue="Y")
# x軸を30度回転
fig.autofmt_xdate()
# x軸の表示間隔を5個ごとに変更
ax.xaxis.set_major_locator(ticker.MultipleLocator(5))

結果

output_6.PNG

全体的に今年の気温は例年よりも高い。

湿度について

fig, ax = plt.subplots(figsize=(12.8, 7.2), dpi=100)
sns.lineplot(data=df, x="m/d", y="hum", hue="Y")

fig.autofmt_xdate()
ax.xaxis.set_major_locator(ticker.MultipleLocator(5))

結果

output_7.PNG

意外なことに湿度は例年よりも低い時が多い。

まとめ

湿度についてはともかく、温度については例年よりも高いことが分かりました。
夏バテの影響は加齢のせいだけでないことがわかり安心しました。

また、pandasのtimestampやdatetimeについて、
少し理解が深まりまったこともよかったなと思います。

参考

0
3
0

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
  3. You can use dark theme
What you can do with signing up
0
3