PythonでRESAS APIを使ってデータをダウンロード
RESASは「Regional Economy Society Analyzing System(地域経済分析システム)」の略。読み方は「リーサス」。市区町村別の産業・経済の情報が提供されており、APIを利用して生データをダウンロードできる。
ここでは、PythonからRESAS APIを利用してデータをJSONやCSV形式でダウンロードする方法を説明する。
- RESAS APIの基本的な使い方
- APIキーを取得
- 仕様と使い方
- RESAS-API一覧
- 例: 都道府県コード
- データを取得
- JSONで保存
- pandas.DataFrameに変換
- CSVで保存
- 例: 市区町村コード
- 都道府県を指定して個別にダウンロード
- 全都道府県のデータを一括ダウンロード
- pandas.DataFrameに変換して連結
- CSVで保存
- JSONで保存
- 例: 一人当たり地方税
政府統計の総合窓口e-StatのAPIをPythonから利用する方法は以下の記事を参照。日本全体や都道府県別のデータが主だがRESASより種類が豊富。
RESAS APIの基本的な使い方
APIキーを取得
RESAS APIを利用するにはAPIキーが必要。以下のページから利用登録する。
利用登録完了後、RESAS-APIトップページからログインすると、マイページにAPIキーが記載されている。
仕様と使い方
仕様は以下のページを参照。
リクエストヘッダーX-API-KEY
にAPIキーを設定し、そのほかのパラメータはクエリ文字列で指定してアクセスする。シンプルなGETメソッドで特に難しいことはない。
詳細は以降の具体例で説明する。
なお、呼び出し回数制限があるので注意。
- RESAS-API - API詳細説明
- 1秒あたりのリクエスト平均数: 5
- リクエスト数/日: 10000
RESAS-API一覧
利用できるデータの一覧は以下のページを参照。
企業数や従業員数などの産業関係のデータから一人当たり賃金、有効求人倍率などの雇用関係のデータまでいろいろある。
例: 都道府県コード
具体例として、都道府県コードをRESAS APIで取得する。都道府県コードはRESAS APIでほかのデータを取得する際に対象の都道府県を指定するためにも使われる。
データを取得
各種ライブラリをインポート。pprintは出力を見やすくするためだけに使用しているのでデータの取得には不要。pandas以外は標準ライブラリに含まれている。pandasのみ別途インストールが必要。
サードパーティモジュールのRequestsを使ってもいいが、ここでは標準ライブラリのurllib.request
を使っている。
import json
import urllib.request
import pprint
import pandas as pd
利用登録して取得したAPIキーを記載したファイルapi_key.json
を用意する。以下のサンプルのようにリクエストヘッダー名X-API-KEY
をキーとする。
with open('setting/api_key_sample.json') as f:
print(f.read())
# {"X-API-KEY":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
これをjson.load()
で辞書(dict
型オブジェクト)として読み込む。
with open('setting/api_key_sample.json') as f:
api_key_sample = json.load(f)
print(api_key_sample)
# {'X-API-KEY': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'}
print(type(api_key_sample))
# <class 'dict'>
なお、リクエストヘッダー名X-API-KEY
をキーとする辞書が作成できれば別の方法でも問題ない。
リクエストヘッダーを含むURLリクエストを行うために、引数にURLとリクエストヘッダー名X-API-KEY
をキーとする辞書を指定してurllib.request.Request()
でリクエストオブジェクトを生成する。
with open('setting/api_key.json') as f:
api_key = json.load(f)
url = 'https://opendata.resas-portal.go.jp/api/v1/prefectures'
req = urllib.request.Request(url, headers=api_key)
print(type(req))
# <class 'urllib.request.Request'>
そのリクエストオブジェクトでURLを開きデータを取得。取得できるのはバイト列(bytes
型オブジェクト)。
with urllib.request.urlopen(req) as response:
data = response.read()
print(type(data))
# <class 'bytes'>
バイト列をdecode()
メソッドで文字列にデコードし、json.loads()
で辞書に変換する。Python3.6以降はjson.loads()
に直接バイト列を指定できるようになったのでdecode()
は不要。
d = json.loads(data.decode())
pprint.pprint(d)
# {'message': None,
# 'result': [{'prefCode': 1, 'prefName': '北海道'},
# {'prefCode': 2, 'prefName': '青森県'},
# {'prefCode': 3, 'prefName': '岩手県'},
# {'prefCode': 4, 'prefName': '宮城県'},
# {'prefCode': 5, 'prefName': '秋田県'},
# {'prefCode': 6, 'prefName': '山形県'},
# {'prefCode': 7, 'prefName': '福島県'},
# {'prefCode': 8, 'prefName': '茨城県'},
# {'prefCode': 9, 'prefName': '栃木県'},
# {'prefCode': 10, 'prefName': '群馬県'},
# {'prefCode': 11, 'prefName': '埼玉県'},
# {'prefCode': 12, 'prefName': '千葉県'},
# {'prefCode': 13, 'prefName': '東京都'},
# {'prefCode': 14, 'prefName': '神奈川県'},
# {'prefCode': 15, 'prefName': '新潟県'},
# {'prefCode': 16, 'prefName': '富山県'},
# {'prefCode': 17, 'prefName': '石川県'},
# {'prefCode': 18, 'prefName': '福井県'},
# {'prefCode': 19, 'prefName': '山梨県'},
# {'prefCode': 20, 'prefName': '長野県'},
# {'prefCode': 21, 'prefName': '岐阜県'},
# {'prefCode': 22, 'prefName': '静岡県'},
# {'prefCode': 23, 'prefName': '愛知県'},
# {'prefCode': 24, 'prefName': '三重県'},
# {'prefCode': 25, 'prefName': '滋賀県'},
# {'prefCode': 26, 'prefName': '京都府'},
# {'prefCode': 27, 'prefName': '大阪府'},
# {'prefCode': 28, 'prefName': '兵庫県'},
# {'prefCode': 29, 'prefName': '奈良県'},
# {'prefCode': 30, 'prefName': '和歌山県'},
# {'prefCode': 31, 'prefName': '鳥取県'},
# {'prefCode': 32, 'prefName': '島根県'},
# {'prefCode': 33, 'prefName': '岡山県'},
# {'prefCode': 34, 'prefName': '広島県'},
# {'prefCode': 35, 'prefName': '山口県'},
# {'prefCode': 36, 'prefName': '徳島県'},
# {'prefCode': 37, 'prefName': '香川県'},
# {'prefCode': 38, 'prefName': '愛媛県'},
# {'prefCode': 39, 'prefName': '高知県'},
# {'prefCode': 40, 'prefName': '福岡県'},
# {'prefCode': 41, 'prefName': '佐賀県'},
# {'prefCode': 42, 'prefName': '長崎県'},
# {'prefCode': 43, 'prefName': '熊本県'},
# {'prefCode': 44, 'prefName': '大分県'},
# {'prefCode': 45, 'prefName': '宮崎県'},
# {'prefCode': 46, 'prefName': '鹿児島県'},
# {'prefCode': 47, 'prefName': '沖縄県'}]}
JSONで保存
json.dump()
でJSON形式で保存できる。
上で取得したバイト列をdecode()
メソッドでデコードした文字列をそのままファイルに保存してもいいが、json.loads()
で辞書に変換してからjson.dump()
で保存すると、引数indent
でインデントを指定したり、引数ensure_ascii
でUnicodeエスケープするかどうかを指定できて便利。
with open('download/pref_code_list.json', 'w') as f:
json.dump(d, f, ensure_ascii=False, indent=4)
デフォルトではJSONの仕様に則って日本語などが\uXXXX
のようなUnicodeエスケープシーケンスで保存され、文字化けしたように見えるので注意。引数ensure_ascii=False
とするとエスケープされずに保存される。
データ部分(レコード部分)のみを保存したい場合はjson.dump()
の引数をd['result']
とする。
pandas.DataFrameに変換
辞書のリストとなっているデータ部分(レコード部分)はpandas.io.json.json_normalize()
でpandas.DataFrame
に変換できる。
df = pd.io.json.json_normalize(d['result'])
print(df.head())
# prefCode prefName
# 0 1 北海道
# 1 2 青森県
# 2 3 岩手県
# 3 4 宮城県
# 4 5 秋田県
実際にデータを利用する際は、都道府県コードから都道府県名を取得したり、都道府県名から都道府県コードを取得したりしたい。
このために、set_index()
でindex
を指定したうえで、列をpandas.Series
として抽出する。
s_code = df.set_index('prefCode')['prefName']
print(s_code.head())
# prefCode
# 1 北海道
# 2 青森県
# 3 岩手県
# 4 宮城県
# 5 秋田県
# Name: prefName, dtype: object
都道府県コードから都道府県名を取得できる。ただし、存在しない都道府県コードを指定するとエラーKeyError
。
print(s_code[13])
# 東京都
# print(s_code[100])
# KeyError: 100
pandas.Series
はto_dict()
で辞書に変換できる。辞書のget()
メソッドを使うと存在しない都道府県コードに対してNone
や指定したデフォルト値を返すようにできる。
d_code = df.set_index('prefCode')['prefName'].to_dict()
print(d_code[13])
# 東京都
# print(d_code[100])
# KeyError: 100
print(d_code.get(13))
# 東京都
print(d_code.get(100))
# None
場合によってはpandas.Series
で例外処理をするより辞書に変換してget()
メソッドを使ったほうが楽。
都道府県名から都道府県コードを取得するのも同様の方法で可能。
s_name = df.set_index('prefName')['prefCode']
print(s_name.head())
# prefName
# 北海道 1
# 青森県 2
# 岩手県 3
# 宮城県 4
# 秋田県 5
# Name: prefCode, dtype: int64
print(s_name['東京都'])
# 13
d_name = df.set_index('prefName')['prefCode'].to_dict()
print(d_name['東京都'])
# 13
print(d_name.get('東京都'))
# 13
CSVで保存
pandas.DataFrame
はto_csv()
メソッドでCSVファイルとして保存できる。
df.to_csv('download/pref_code_list.csv', index=None)
CSVファイルをpandas.DataFrame
として読み出したい場合はpandas.read_csv()
関数を使う。
df_from_csv = pd.read_csv('download/pref_code_list.csv')
print(df_from_csv.head())
# prefCode prefName
# 0 1 北海道
# 1 2 青森県
# 2 3 岩手県
# 3 4 宮城県
# 4 5 秋田県
例: 市区町村コード
次の具体例として、市区町村コードをRESAS APIで取得する。
都道府県を指定して個別にダウンロード
都道府県を指定して個別にダウンロードする場合は、上の都道府県コードの例とほぼ同じ。
パラメータとして都道府県コードを指定する必要がある。urllib.parse.urlencode()
に辞書を渡してクエリ文字列を取得する。パラメータが複数ある場合やURLエンコード(パーセントエンコード)が必要な場合も、urllib.parse.urlencode()
が処理してくれる。
import json
import urllib.parse
import urllib.request
import pprint
import pandas as pd
url_base = 'https://opendata.resas-portal.go.jp/api/v1/cities'
p = {'prefCode': 13}
url = url_base + '?' + urllib.parse.urlencode(p)
print(url)
# https://opendata.resas-portal.go.jp/api/v1/cities?prefCode=13
この例の場合は都道府県コードを数値で指定するだけなので、単純に文字列を連結してもOK。
pref_code = 13
url = url_base + '?prefCode=' + str(pref_code)
print(url)
# https://opendata.resas-portal.go.jp/api/v1/cities?prefCode=13
あとの流れは上の都道府県コードの例と同じ。
with open('setting/api_key.json') as f:
api_key = json.load(f)
req = urllib.request.Request(url, headers=api_key)
with urllib.request.urlopen(req) as response:
data = response.read()
d = json.loads(data.decode())
pprint.pprint(d, width=100)
# {'message': None,
# 'result': [{'bigCityFlag': '3', 'cityCode': '13101', 'cityName': '千代田区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13102', 'cityName': '中央区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13103', 'cityName': '港区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13104', 'cityName': '新宿区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13105', 'cityName': '文京区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13106', 'cityName': '台東区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13107', 'cityName': '墨田区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13108', 'cityName': '江東区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13109', 'cityName': '品川区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13110', 'cityName': '目黒区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13111', 'cityName': '大田区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13112', 'cityName': '世田谷区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13113', 'cityName': '渋谷区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13114', 'cityName': '中野区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13115', 'cityName': '杉並区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13116', 'cityName': '豊島区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13117', 'cityName': '北区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13118', 'cityName': '荒川区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13119', 'cityName': '板橋区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13120', 'cityName': '練馬区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13121', 'cityName': '足立区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13122', 'cityName': '葛飾区', 'prefCode': 13},
# {'bigCityFlag': '3', 'cityCode': '13123', 'cityName': '江戸川区', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13201', 'cityName': '八王子市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13202', 'cityName': '立川市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13203', 'cityName': '武蔵野市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13204', 'cityName': '三鷹市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13205', 'cityName': '青梅市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13206', 'cityName': '府中市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13207', 'cityName': '昭島市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13208', 'cityName': '調布市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13209', 'cityName': '町田市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13210', 'cityName': '小金井市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13211', 'cityName': '小平市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13212', 'cityName': '日野市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13213', 'cityName': '東村山市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13214', 'cityName': '国分寺市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13215', 'cityName': '国立市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13218', 'cityName': '福生市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13219', 'cityName': '狛江市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13220', 'cityName': '東大和市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13221', 'cityName': '清瀬市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13222', 'cityName': '東久留米市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13223', 'cityName': '武蔵村山市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13224', 'cityName': '多摩市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13225', 'cityName': '稲城市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13227', 'cityName': '羽村市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13228', 'cityName': 'あきる野市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13229', 'cityName': '西東京市', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13303', 'cityName': '瑞穂町', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13305', 'cityName': '日の出町', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13307', 'cityName': '檜原村', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13308', 'cityName': '奥多摩町', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13361', 'cityName': '大島町', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13362', 'cityName': '利島村', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13363', 'cityName': '新島村', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13364', 'cityName': '神津島村', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13381', 'cityName': '三宅村', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13382', 'cityName': '御蔵島村', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13401', 'cityName': '八丈町', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13402', 'cityName': '青ヶ島村', 'prefCode': 13},
# {'bigCityFlag': '0', 'cityCode': '13421', 'cityName': '小笠原村', 'prefCode': 13}]}
JSONで保存したい場合はjson.dump()
、CSVで保存したい場合はpandas.io.json.json_normalize()
でpandas.DataFrame
に変換してからto_csv()
を使う。
全都道府県のデータを一括ダウンロード
個別の都道府県のデータではなく、全都道府県の市区町村のデータ一覧を取得する方法を説明する。
pandas.DataFrameに変換して連結
空のリストを作成し、全都道府県(都道府県コード1〜47)までのデータをpandas.DataFrame
に変換して格納、pandas.concat()
関数で連結する。
l = []
url_base = 'https://opendata.resas-portal.go.jp/api/v1/cities'
for pref_code in range(1, 48):
url = url_base + '?prefCode=' + str(pref_code)
req = urllib.request.Request(url, headers=api_key)
with urllib.request.urlopen(req) as response:
data = response.read()
d = json.loads(data.decode())
l.append(pd.io.json.json_normalize(d['result']))
df_all = pd.concat(l, ignore_index=True)
全都道府県のデータを取得するのに1分ほどかかる。
1920行のpandas.DataFrame
が生成される。都道府県コードを表すprefCode
列のみが数値型。
print(df_all.head())
# bigCityFlag cityCode cityName prefCode
# 0 2 01100 札幌市 1
# 1 1 01101 札幌市中央区 1
# 2 1 01102 札幌市北区 1
# 3 1 01103 札幌市東区 1
# 4 1 01104 札幌市白石区 1
print(df_all.shape)
# (1920, 4)
print(df_all.dtypes)
# bigCityFlag object
# cityCode object
# cityName object
# prefCode int64
# dtype: object
特別区・行政区フラグbigCityFlag
を使って政令指定都市の市の一覧を取得したり、特定の都道府県の政令指定都市の区の一覧を取得したりできる。
print(df_all.query('bigCityFlag == "2"'))
# bigCityFlag cityCode cityName prefCode
# 0 2 01100 札幌市 1
# 265 2 04100 仙台市 4
# 529 2 11100 さいたま市 11
# 602 2 12100 千葉市 12
# 724 2 14100 横浜市 14
# 743 2 14130 川崎市 14
# 751 2 14150 相模原市 14
# 785 2 15100 新潟市 15
# 1020 2 22100 静岡市 22
# 1024 2 22130 浜松市 22
# 1065 2 23100 名古屋市 23
# 1183 2 26100 京都市 26
# 1220 2 27100 大阪市 27
# 1245 2 27140 堺市 27
# 1294 2 28100 神戸市 28
# 1451 2 33100 岡山市 33
# 1482 2 34100 広島市 34
# 1627 2 40100 北九州市 40
# 1635 2 40130 福岡市 40
# 1742 2 43100 熊本市 43
print(df_all.query('bigCityFlag == "1" & prefCode == 14'))
# bigCityFlag cityCode cityName prefCode
# 725 1 14101 横浜市鶴見区 14
# 726 1 14102 横浜市神奈川区 14
# 727 1 14103 横浜市西区 14
# 728 1 14104 横浜市中区 14
# 729 1 14105 横浜市南区 14
# 730 1 14106 横浜市保土ケ谷区 14
# 731 1 14107 横浜市磯子区 14
# 732 1 14108 横浜市金沢区 14
# 733 1 14109 横浜市港北区 14
# 734 1 14110 横浜市戸塚区 14
# 735 1 14111 横浜市港南区 14
# 736 1 14112 横浜市旭区 14
# 737 1 14113 横浜市緑区 14
# 738 1 14114 横浜市瀬谷区 14
# 739 1 14115 横浜市栄区 14
# 740 1 14116 横浜市泉区 14
# 741 1 14117 横浜市青葉区 14
# 742 1 14118 横浜市都筑区 14
# 744 1 14131 川崎市川崎区 14
# 745 1 14132 川崎市幸区 14
# 746 1 14133 川崎市中原区 14
# 747 1 14134 川崎市高津区 14
# 748 1 14135 川崎市多摩区 14
# 749 1 14136 川崎市宮前区 14
# 750 1 14137 川崎市麻生区 14
# 752 1 14151 相模原市緑区 14
# 753 1 14152 相模原市中央区 14
# 754 1 14153 相模原市南区 14
市区町村コードから市区町村名を取得したり、市区町村名から市区町村コードを取得したりしたい場合は、上述の都道府県コードの例のようにset_index()
でindex
を指定したうえで、列をpandas.Series
として抽出する。
s_code = df_all.set_index('cityCode')['cityName']
print(s_code.head())
# cityCode
# 01100 札幌市
# 01101 札幌市中央区
# 01102 札幌市北区
# 01103 札幌市東区
# 01104 札幌市白石区
# Name: cityName, dtype: object
print(s_code['14100'])
# 横浜市
s_name = df_all.set_index('cityName')['cityCode']
print(s_name.head())
# cityName
# 札幌市 01100
# 札幌市中央区 01101
# 札幌市北区 01102
# 札幌市東区 01103
# 札幌市白石区 01104
# Name: cityCode, dtype: object
print(s_name['横浜市'])
# 14100
CSVで保存
CSVファイルをとして保存するにはto_csv()
メソッドを使う。
df_all.to_csv('download/city_code_list.csv', index=None)
JSONで保存
JSONファイルとして保存するにはto_json()
メソッドを使う。
df_all.to_json('download/city_code_list.json', orient='records', force_ascii=False)
records
形式では辞書のリストで保存される。
保存したJSONファイルの読み込み方法は以下の通り。
json.load()
で読み込み。
with open('download/city_code_list.json') as f:
data_json = json.load(f)
print(type(data_json))
# <class 'list'>
pprint.pprint(data_json[:5])
# [{'bigCityFlag': '2', 'cityCode': '01100', 'cityName': '札幌市', 'prefCode': 1},
# {'bigCityFlag': '1', 'cityCode': '01101', 'cityName': '札幌市中央区', 'prefCode': 1},
# {'bigCityFlag': '1', 'cityCode': '01102', 'cityName': '札幌市北区', 'prefCode': 1},
# {'bigCityFlag': '1', 'cityCode': '01103', 'cityName': '札幌市東区', 'prefCode': 1},
# {'bigCityFlag': '1', 'cityCode': '01104', 'cityName': '札幌市白石区', 'prefCode': 1}]
print(len(data_json))
# 1920
pandas.read_json()
でpandas.DataFrame
として読み込み。
df_from_json = pd.read_json('download/city_code_list.json')
print(df_from_json.head())
# bigCityFlag cityCode cityName prefCode
# 0 2 1100 札幌市 1
# 1 1 1101 札幌市中央区 1
# 2 1 1102 札幌市北区 1
# 3 1 1103 札幌市東区 1
# 4 1 1104 札幌市白石区 1
print(df_from_json.shape)
# (1920, 4)
例: 一人当たり地方税
最後の例として、一人当たり地方税をRESAS APIで取得する。
パラメータとして都道府県コードと市区町村コードを指定する。
これまでの例との違いは、取得できるJSONのresult
キーの値がレコード形式(辞書のリスト)ではない点。
import json
import urllib.parse
import urllib.request
import pprint
import pandas as pd
url_base = 'https://opendata.resas-portal.go.jp/api/v1/municipality/taxes/perYear'
p = {'prefCode': 13, 'cityCode': 13103}
url = url_base + '?' + urllib.parse.urlencode(p)
print(url)
# https://opendata.resas-portal.go.jp/api/v1/municipality/taxes/perYear?prefCode=13&cityCode=13103
with open('setting/api_key.json') as f:
api_key = json.load(f)
req = urllib.request.Request(url, headers=api_key)
with urllib.request.urlopen(req) as response:
data = response.read()
d = json.loads(data.decode())
pprint.pprint(d)
# {'message': None,
# 'result': {'cityCode': '13103',
# 'cityName': '港区',
# 'data': [{'value': 335, 'year': 2008},
# {'value': 326, 'year': 2009},
# {'value': 286, 'year': 2010},
# {'value': 277, 'year': 2011},
# {'value': 254, 'year': 2012},
# {'value': 262, 'year': 2013},
# {'value': 304, 'year': 2014}],
# 'prefCode': 13,
# 'prefName': '東京都'}}
これをpandas.DataFrame
に変換する場合、pandas.io.json.json_normalize()
の引数にそのまま指定するとうまくいかない。
print(pd.io.json.json_normalize(d['result']))
# cityCode cityName data \
# 0 13103 港区 [{'year': 2008, 'value': 335}, {'year': 2009, ...
# prefCode prefName
# 0 13 東京都
引数record_path
にレコード形式(辞書のリスト)のデータが格納されているキーを指定するとOK。
print(pd.io.json.json_normalize(d['result'], record_path='data'))
# value year
# 0 335 2008
# 1 326 2009
# 2 286 2010
# 3 277 2011
# 4 254 2012
# 5 262 2013
# 6 304 2014
複数の市区町村のデータを連結したい場合など、同階層の値も含むpandas.DataFrame
を取得したい場合は引数meta
を指定する。
print(pd.io.json.json_normalize(d['result'], record_path='data',
meta=['cityCode', 'cityName', 'prefCode', 'prefName']))
# value year cityCode cityName prefCode prefName
# 0 335 2008 13103 港区 13 東京都
# 1 326 2009 13103 港区 13 東京都
# 2 286 2010 13103 港区 13 東京都
# 3 277 2011 13103 港区 13 東京都
# 4 254 2012 13103 港区 13 東京都
# 5 262 2013 13103 港区 13 東京都
# 6 304 2014 13103 港区 13 東京都
詳細は以下の記事を参照。
上で説明した全都道府県のデータを一括ダウンロードする場合は都道府県コード1〜47を連番で指定すればよかったが、複数の市区町村のデータを一括で取得したい場合は市区町村コードのリストが必要。
上で取得した市区町村コードを含むpandas.DataFrame
から市区町村コードのリストを取得する例を示す。
query()
メソッドで条件を満たす行を抽出。
df_city = pd.read_csv('download/city_code_list.csv')
print(df_city.query('prefCode == 40 & bigCityFlag == 1'))
# bigCityFlag cityCode cityName prefCode
# 1628 1 40101 北九州市門司区 40
# 1629 1 40103 北九州市若松区 40
# 1630 1 40105 北九州市戸畑区 40
# 1631 1 40106 北九州市小倉北区 40
# 1632 1 40107 北九州市小倉南区 40
# 1633 1 40108 北九州市八幡東区 40
# 1634 1 40109 北九州市八幡西区 40
# 1636 1 40131 福岡市東区 40
# 1637 1 40132 福岡市博多区 40
# 1638 1 40133 福岡市中央区 40
# 1639 1 40134 福岡市南区 40
# 1640 1 40135 福岡市西区 40
# 1641 1 40136 福岡市城南区 40
# 1642 1 40137 福岡市早良区 40
そこから市区町村コードの列を選択し、values
属性でNumPy配列ndarray
を得る。
a = df_city.query('prefCode == 40 & bigCityFlag == 1')['cityCode'].values
print(a)
# [40101 40103 40105 40106 40107 40108 40109 40131 40132 40133 40134 40135
# 40136 40137]
print(type(a))
# <class 'numpy.ndarray'>
for code in a:
print(code)
# 40101
# 40103
# 40105
# 40106
# 40107
# 40108
# 40109
# 40131
# 40132
# 40133
# 40134
# 40135
# 40136
# 40137
NumPy配列ndarray
をfor文で回し、各市区町村コードでAPIにアクセスすればOK。