今までRでしか取得したことがなく,Pythonでは初めてだったのでメモ
使い方の流れ
- 利用登録してAPIキーを取得
- RESAS-API - API概要を見て,取得するデータを決める
- 取得したいデータのURLにGETリクエストを送れば(アクセスすれば)JSON形式でデータを取得できる
urllib
ライブラリのurllib.request.Request()
メソッドで取得できる- パラメータ(
?cityCode=11362
みたいなやつ)を付加する場合はurllib.parse.urlencode()
を使う
- 取得したJSONデータを整形する
json
ライブラリのjson.loads()
でpythonの辞書型に変換pandas
のpd.io.json.json_normalize()
などで辞書型をDataFrame型に変換
コードの例
RESASデータ取得用の関数
import urllib import pandas as pd import json api_key = {"X-API-KEY": "ここに取得したAPIキーを入力"} def get_resas_data(params: dict, api_path: str, api_key: dict) -> dict: api_endpoint = "https://opendata.resas-portal.go.jp/" url = api_endpoint + api_path url = (url + "?" + urllib.parse.urlencode(params)) if (params != None) else url req = urllib.request.Request(url, headers = api_key) with urllib.request.urlopen(req) as res: response = res.read() resas_data_dict = json.loads(response.decode()) return resas_data_dict
例:都道府県一覧の取得
# 都道府県一覧の取得 resas_data = get_resas_data(params=None, api_path="api/v1/prefectures", api_key=api_key) prefectures = pd.io.json.json_normalize(resas_data['result'])
例:市区町村一覧の取得
cities = pd.DataFrame() for i in range(1,48): resas_data = get_resas_data(params={"prefCode": i}, api_path="api/v1/cities", api_key=api_key) cities_i = pd.io.json.json_normalize(resas_data['result']) cities = pd.concat([cities, cities_i], axis=0)
例:出生数・死亡数/転入数・転出数の取得
都道府県や市区町村とは異なり,こういうデータは返ってくるJSONがネスト(入れ子)していて整形が面倒。
pd.io.json.json_normalize()
やpandasの前処理関数(例えばpd.DataFrame.pivot()
)を駆使して整形していく。
例えば,次のように,リストと文字列が入っている辞書型データは,pd.io.json.json_normalize()
できれいにデータフレームに変換できる
# 辞書の入ったリストと文字列を含む辞書型データ data_dict = {'data': [{'value': 34780, 'year': 1995}, {'value': 36035, 'year': 2000}, {'value': 46769, 'year': 2005}], 'label': '総人口'} # record_pathにリストのキーを指定,metaにそれ以外のキーを指定 pd.io.json.json_normalize(data_dict, record_path="data", meta=["label"])
データの取得
といった知識をもとに書いたコードがこれ
api_path = "api/v1/population/sum/estimate" params={"prefCode": 13, "cityCode": 13101} resas_data = get_resas_data(params=params, api_path=api_path, api_key=api_key) data_list = resas_data["result"]["data"] for i in range(len(data_list)): resas_df_i = pd.io.json.json_normalize(data_list[i], record_path="data", meta=["label"]) resas_df_i = resas_df_i.pivot(index="year", columns="label", values="value").reset_index() resas_df = resas_df_i if i == 0 else pd.merge(resas_df, resas_df_i, on="year")