気象APIをpandasでCSVにしてみる

以下の「気象データ Web API」を使わせてもらって、CSV化やStreamlit化をやってみました。

https://www.cultivationdata.net/weather-web-api.html

https://api.cultivationdata.net/past?no=地点番号

地点番号は調べていた時点では出身に近いからという理由で輪島市(47600)を選択していました。

詰まったところ

  • 一桁の月日の場合は01ではなく1
  • json_normalizeだけはでうまくいかない。(やり方を見つけられなかった。)
  • たまに数値の後ろに記号が付く(https://www.data.jma.go.jp/gmd/risk/obsdl/top/help4.html#data_hyouki)

上記詰まったところを回避するために回りくどいコードになっている個所もあります。

前日のデータをCSVに追加する

import requests
import json
import pandas as pd
import datetime
import os
####################
# https://www.cultivationdata.net/weather-web-api.html
# 輪島 一か月分
# https://api.cultivationdata.net/past?no=47600&year=2023&month=10
# 輪島 前日分
# https://api.cultivationdata.net/past?no=47600
####################
#########################
# datetimeモジュールを使用
#########################
t_delta = datetime.timedelta(hours=9)
JST = datetime.timezone(t_delta, 'JST')
yesterday = datetime.datetime.now(JST) - datetime.timedelta(days=1) # 2023-02-21 11:01:59.856959+09:00
# yesterday_YYYY_MM_DD = datetime.datetime.strftime(yesterday, '%Y-%m-%d') # 2023-02-21
yesterday_YYYY_MM_DD = datetime.datetime.strftime(yesterday, '%Y-%#m-%#d') # 2023-2-21 %#m-%#dで0埋めしない。
getNo=47600


res = requests.get(f"https://api.cultivationdata.net/past?no={getNo}",verify=False)


df = pd.json_normalize(res.json()['輪島'][yesterday_YYYY_MM_DD])
# 先頭に日付を追加
df.insert(0, '日付', yesterday_YYYY_MM_DD)
# ファイル有無チェック
if os.path.isfile('kisyo.csv'):
    df.to_csv('kisyo.csv', index=False, header=False, mode='a')
else:
    df.to_csv('kisyo.csv', index=False)

指定年月のデータをCSV化

import requests
import json
import pandas as pd
import datetime
import os
import matplotlib.pyplot as plt
import japanize_matplotlib
####################
# https://www.cultivationdata.net/weather-web-api.html
# 輪島 一か月分
# https://api.cultivationdata.net/past?no=47600&year=2023&month=10
# 輪島 前日分
# https://api.cultivationdata.net/past?no=47600
####################
#########################
# datetimeモジュールを使用
#########################
t_delta = datetime.timedelta(hours=9)
JST = datetime.timezone(t_delta, 'JST')
yesterday = datetime.datetime.now(JST) - datetime.timedelta(days=1) # 2023-02-21 11:01:59.856959+09:00
# yesterday_YYYY_MM_DD = datetime.datetime.strftime(yesterday, '%Y-%m-%d') # 2023-02-21
yesterday_YYYY_MM_DD = datetime.datetime.strftime(yesterday, '%Y-%#m-%#d') # 2023-2-21 %#m-%#dで0埋めしない。
getNo = 47600
getYear = 2023
getMonth = 10


res = requests.get(f"https://api.cultivationdata.net/past?no={getNo}&year={getYear}&month={getMonth}",verify=False)

df = pd.DataFrame()
data = json.loads( res.text )
for day in data['輪島']:
    df_tmp = pd.json_normalize(data['輪島'][day])
    # 先頭に日付を追加
    df_tmp.insert(0, '日付', day)
    df = pd.concat([df, df_tmp], ignore_index=True, axis=0)

# https://www.data.jma.go.jp/gmd/risk/obsdl/top/help4.html#data_hyouki
# ↑の表記は一旦無視する
df = df.replace(r' \)', '', regex=True)

# ファイル有無チェック
if os.path.isfile('kisyo.csv'):
    df.to_csv('kisyo.csv', index=False, header=False, mode='a')
else:
    df.to_csv('kisyo.csv', index=False)

API取得したものをStreamlitに表示してみる

やってみましたが取得に時間がかかるので、実運用時はCSV保存しています。

import streamlit as st
import requests
import json
import pandas as pd
import datetime
import os
import matplotlib.pyplot as plt
import japanize_matplotlib
####################
# https://www.cultivationdata.net/weather-web-api.html
# 輪島 一か月分
# https://api.cultivationdata.net/past?no=47600&year=2023&month=10
# 輪島 前日分
# https://api.cultivationdata.net/past?no=47600
####################
#########################
# 日付絞り込み
#########################
select_day = st.sidebar.date_input('日付を指定してください', datetime.date.today())

#########################
# datetimeモジュールを使用
#########################
t_delta = datetime.timedelta(hours=9)
JST = datetime.timezone(t_delta, 'JST')
yesterday = datetime.datetime.now(JST) - datetime.timedelta(days=1) # 2023-02-21 11:01:59.856959+09:00
# yesterday_YYYY_MM_DD = datetime.datetime.strftime(yesterday, '%Y-%m-%d') # 2023-02-21
yesterday_YYYY_MM_DD = datetime.datetime.strftime(yesterday, '%Y-%#m-%#d') # 2023-2-21 %#m-%#dで0埋めしない。
getNo = 47600
getYear = select_day.year
getMonth = select_day.month


res = requests.get(f"https://api.cultivationdata.net/past?no={getNo}&year={getYear}&month={getMonth}",verify=False)


df = pd.DataFrame()
data = json.loads( res.text )
for day in data['輪島']:
    df_tmp = pd.json_normalize(data['輪島'][day])
    # 先頭に日付を追加
    df_tmp.insert(0, '日付', day)
    df = pd.concat([df, df_tmp], ignore_index=True, axis=0)

# https://www.data.jma.go.jp/gmd/risk/obsdl/top/help4.html#data_hyouki
# ↑の表記は一旦無視する
df = df.replace(r' \)', '', regex=True)

c1,c2,c3,c4 = 'lightskyblue', 'black', 'red', 'black'
fig, ax = plt.subplots(1,1,squeeze=False,figsize=(13,5))

ax0_0 = ax[0,0]
ax0_0.plot(df["日付"], df["平均気温"].astype(float), marker='o', color=c2, label="平均気温")
ax0_0.plot(df["日付"], df["最高気温"].astype(float), marker='o', color=c3, label="最高気温")
ax0_0.plot(df["日付"], df["最低気温"].astype(float), marker='o', color=c1, label="最低気温")
ax0_0.set_title("気温データ")
ax0_0.set_xlabel("日付")
ax0_0.set_ylabel("気温")
ax0_0.legend()
plt.setp(ax0_0.get_xticklabels(), rotation=90, ha="right")

st.pyplot(fig)

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA