はじめに
RESAS は日本の地域経済データを取得できるサービスです
地域経済分析システム(RESAS:リーサス)は、地方創生の様々な取り組みを情報面から支援するために、経済産業省と内閣官房デジタル田園都市国家構想実現会議事務局が提供しています。
RESAS-API に利用登録すると、 REST API でデータを取得することもできます
今回は Elixir Livebook 上で Explorer を使って、 RESAS のデータを分析、可視化してみたいと思います
今回実装したノートブックの全量はこちら
出典
この記事はRESAS(地域経済分析システム)のデータを加工して作成しています
実行環境
このリポジトリーの Docker コンテナ上で実行しました
RESAS-API の使い方
公式サイトから「利用登録」に進んで、必要項目を入力して仮登録します
本登録用のメールに記載されているリンクにアクセスすれば登録完了です
ここに表示されるAPIキーを利用します
利用登録後は、 RESAS-API マイページの最下部にもAPIキーが表示されます
セットアップ
Livebook を起動してノートブックを開きます
以下のコードをノートブック上で実行してください
Mix.install([
{:httpoison, "~> 1.8"},
{:json, "~> 1.4"},
{:explorer, "~> 0.3"},
{:kino, "~> 0.7"},
{:kino_vega_lite, "~> 0.1.4"}
])
必要なライブラリをインストールします
- httpoison: REST API を呼び出す
- json: JSON をエンコード、デコードする
- explorer: データ分析
- kino: 実行結果を可視化する
- kino_vega_lite: データをグラフ化する
以下のコードを実行するとテキストエリアが表示されるので、 Tellus で作っておいたトークンを入力します
# RESAS のAPIキーを入力する
api_key_input = Kino.Input.password("API_KEY")
ベースAPIを設定します
base_url = "https://opendata.resas-portal.go.jp"
エイリアスを指定しておきます
alias Explorer.DataFrame
alias Explorer.Series
RESAS の認証
RESAS の認証は API キーをヘッダーに入れるだけです
認証ヘッダーを設定しておきます
auth_header = {"X-API-KEY", Kino.Input.read(api_key_input)}
都道府県一覧の取得
公式リファレンスを参照すれば、どういう API をどう呼び出せばどういう内容が返ってくるのかが分かります
都道府県一覧は以下のようにして呼び出します
prefectures_url = "#{base_url}/api/v1/prefectures"
prefectures =
prefectures_url
|> HTTPoison.get!([auth_header])
|> then(&JSON.decode!(&1.body))
レスポンスの result
に都道府県マップのリストが入っていますね
DataFrame.new()
にマップのリストを渡すだけでデータフレームが出来上がります
prefectures_df = DataFrame.new(prefectures["result"])
データフレームのままだと見にくいので、表形式にしてみます
Kino.DataTable.new()
にデータフレームをそのまま渡すだけです
Kino.DataTable.new(prefectures_df, sorting_enabled: true)
ページングやソートができる表として表示されました
続いて大分県の都道府県コードをデータフレームから取得してみましょう
oita_pref_code =
prefectures_df
# "prefName" が "大分県" の行を抽出
|> DataFrame.filter_with(&Series.equal(&1["prefName"], "大分県"))
# "prefCode" の列を選択
|> DataFrame.pull("prefCode")
# 先頭のデータを取得
|> Series.first()
|> dbg()
最後に dbg
を入れたことにより、各パイプラインの途中経過を見ることができます
市区町村一覧の取得
都道府県コードを指定して市区町村一覧を取得します
空文字 ""
が渡された場合は全都道府県の市区町村になります
get_cities = fn pref_code ->
query =
case pref_code do
"" ->
""
pref_code ->
"?prefCode=#{pref_code}"
end
cities_url = "#{base_url}/api/v1/cities#{query}"
cities_url
|> HTTPoison.get!([auth_header])
|> then(&JSON.decode!(&1.body))
|> then(&(&1["result"]))
end
まず全国の市区町村を取得してみましょう
all_cities_df =
""
|> get_cities.()
|> DataFrame.new()
all_cities_df
|> Kino.DataTable.new(sorting_enabled: true)
全国で 1922 の市区町村が取得できました
bigCityFlag は「特別区・行政区フラグ」で、以下の値を持ちます
- 0:一般の市区町村
- 1:政令指定都市の区
- 2:政令指定都市の市
- 3:東京都23区
大分県内の市町村を取得してみましょう
oita_cities_df =
oita_pref_code
|> get_cities.()
|> DataFrame.new()
oita_cities_df
|> Kino.DataTable.new(sorting_enabled: true)
18 市町村が取得できました
後で使うために大分市の市区町村コードを取得しておきます
oita_city_code =
oita_cities_df
|> DataFrame.filter_with(&Series.equal(&1["cityName"], "大分市"))
|> DataFrame.pull("cityCode")
|> Series.first()
|> dbg()
特別区・行政区のある都道府県
大分県に特別区・行政区があるか見てみましょう
oita_cities_df
|> DataFrame.filter_with(&Series.not_equal(&1["bigCityFlag"], "0"))
|> Kino.DataTable.new(sorting_enabled: true)
大分県に特別区・行政区はないですね
全国に特別区・行政区がある都道府県はどれくらいあるのでしょう
all_cities_df
# bigCityFlag が 0 でない行を抽出する
|> DataFrame.filter_with(&Series.not_equal(&1["bigCityFlag"], "0"))
# 都道府県コードで重複排除する
|> DataFrame.distinct(["prefCode"])
# 都道府県一覧データフレームと結合する
|> DataFrame.join(prefectures_df)
|> Kino.DataTable.new(sorting_enabled: true)
|> dbg()
はい、上画像の 16 都道府県は特別区・行政区があります
人口構成の取得
いよいよ人口構成(年代別の人口)を取得します
人口構成 API は都道府県コードが必須、市区町コードは指定しない場合 -
を渡します
get_population_composition = fn pref_code, city_code ->
query =
"?prefCode=#{pref_code}&cityCode="
<>
case city_code do
"" ->
"-"
city_code ->
city_code
end
url = "#{base_url}/api/v1/population/composition/perYear#{query}"
url
|> HTTPoison.get!([auth_header])
|> then(&JSON.decode!(&1.body))
|> then(&(&1["result"]["data"]))
end
大分県全体の人口構成を取得します
population_composition = get_population_composition.(oita_pref_code, "")
レスポンスは以下のような、ちょっと特殊な形になっています
%{
"data" => [
%{"value" => 1239655, "year" => 1960},
%{"value" => 1187480, "year" => 1965},
...
%{"value" => 946917, "year" => 2040},
%{"value" => 896653, "year" => 2045}
],
"label" => "総人口"
},
%{
"data" => [
%{"rate" => 32.6, "value" => 405103, "year" => 1960},
%{"rate" => 27.7, "value" => 329717, "year" => 1965},
...
%{"rate" => 11, "value" => 105073, "year" => 2040},
%{"rate" => 11, "value" => 99257, "year" => 2045}
],
"label" => "年少人口"
},
%{
"data" => [
%{"rate" => 60.1, "value" => 746271, "year" => 1960},
%{"rate" => 63.9, "value" => 759450, "year" => 1965},
...
%{"rate" => 50.8, "value" => 481160, "year" => 2040},
%{"rate" => 49.5, "value" => 444584, "year" => 2045}
],
"label" => "生産年齢人口"
},
%{
"data" => [
%{"rate" => 7.1, "value" => 88281, "year" => 1960},
%{"rate" => 8.2, "value" => 98313, "year" => 1965},
...
%{"rate" => 38, "value" => 360684, "year" => 2040},
%{"rate" => 39.3, "value" => 352812, "year" => 2045}
],
"label" => "老年人口"
}
]
このままだとデータフレームにできないので、ちょっと加工してからデータフレームにします
population_composition_df =
population_composition
|> Enum.flat_map(fn data ->
data["data"]
|> Enum.map(fn datum ->
Map.merge(datum, %{"label" => data["label"]})
end)
end)
|> DataFrame.new()
population_composition_df
|> Kino.DataTable.new(sorting_enabled: true)
ではグラフにしてみましょう
楽をしたいので Smart Cells を使います
セル追加するときに +Smart
から Chart
を選びます
すると以下のようなセルが追加されます
以下のように入力してセルを実行しましょう
- CHARTING: 大分県人口構成推移
- WIDTH: 700
- HEIGHT: 400
- Data: population_composition_df
- Chart: line
- x-axis: year
- y-axis: value
- Color: label
すると、以下のようにグラフが表示できます
ちなみに2015年までは実績で、それより後は予測値です
人口減少と高齢化が見えて悲しいですね
大分市で見てみましょう
oita_city_population_composition_df =
oita_pref_code
|> get_population_composition.(oita_city_code)
|> Enum.flat_map(fn data ->
data["data"]
|> Enum.map(fn datum ->
Map.merge(datum, %{"label" => data["label"]})
end)
end)
|> DataFrame.new()
oita_city_population_composition_df
|> Kino.DataTable.new(sorting_enabled: true)
大分県全体と比べるとマシですが、やはり人口減少と高齢化が進むように予測されています
まとめ
RESAS-API と Explore を使えばもっと色々な分析、可視化ができそうですね