Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

RESAS から人口構成を取得する

livebooks/resas/population.livemd

RESAS から人口構成を取得する

Mix.install([
  {:req, "~> 0.5"},
  {:explorer, "~> 0.9"},
  {:kino, "~> 0.14"},
  {:kino_vega_lite, "~> 0.1"}
])

情報の設定

このノートブックはRESAS(地域経済分析システム)のデータを加工して作成しています

# RESAS のAPIキーを入力する
api_key_input = Kino.Input.password("API_KEY")
base_url = "https://opendata.resas-portal.go.jp"
alias Explorer.DataFrame
alias Explorer.Series
require Explorer.DataFrame

RESAS の認証

auth_header = {"X-API-KEY", Kino.Input.read(api_key_input)}
Kino.nothing()

都道府県一覧の取得

prefectures_url = "#{base_url}/api/v1/prefectures"

prefectures =
  prefectures_url
  |> Req.get!(headers: [auth_header])
  |> Map.get(:body)
prefectures_df = DataFrame.new(prefectures["result"])
Kino.DataTable.new(prefectures_df)
oita_pref_code =
  prefectures_df
  # "prefName" が "大分県" の行を抽出
  |> DataFrame.filter(prefName == "大分県")
  # "prefCode" の列を選択
  |> DataFrame.pull("prefCode")
  # 先頭のデータを取得
  |> Series.first()
  |> dbg()

市区町村一覧の取得

get_cities = fn pref_code ->
  query =
    case pref_code do
      "" ->
        ""

      pref_code ->
        "?prefCode=#{pref_code}"
    end

  "#{base_url}/api/v1/cities#{query}"
  |> Req.get!(headers: [auth_header])
  |> then(& &1.body["result"])
end
all_cities_df =
  ""
  |> get_cities.()
  |> DataFrame.new()

Kino.DataTable.new(all_cities_df)
oita_cities_df =
  oita_pref_code
  |> get_cities.()
  |> DataFrame.new()

Kino.DataTable.new(oita_cities_df)
oita_city_code =
  oita_cities_df
  |> DataFrame.filter(cityName == "大分市")
  |> DataFrame.pull("cityCode")
  |> Series.first()
  |> dbg()

特別区・行政区のある都道府県

bigCityFlag: 特別区・行政区フラグ

  • 0:一般の市区町村
  • 1:政令指定都市の区
  • 2:政令指定都市の市
  • 3:東京都23区
oita_cities_df
|> DataFrame.filter(bigCityFlag != "0")
|> Kino.DataTable.new()
all_cities_df
# bigCityFlag が 0 でない行を抽出する
|> DataFrame.filter(bigCityFlag != "0")
# 都道府県コードで重複排除する
|> DataFrame.distinct(["prefCode"])
# 都道府県一覧データフレームと結合する
|> DataFrame.join(prefectures_df)
|> Kino.DataTable.new()
|> dbg()

人口構成の取得

get_population_composition = fn pref_code, city_code ->
  query =
    "?prefCode=#{pref_code}&cityCode=" <>
      case city_code do
        "" ->
          "-"

        city_code ->
          city_code
      end

  "#{base_url}/api/v1/population/composition/perYear#{query}"
  |> Req.get!(headers: [auth_header])
  |> then(&amp; &amp;1.body["result"]["data"])
end
population_composition = get_population_composition.(oita_pref_code, "")
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()

Kino.DataTable.new(population_composition_df)
VegaLite.new(width: 700, height: 400, title: "大分県人口構成推移")
|> VegaLite.data_from_values(population_composition_df, only: ["year", "value", "label"])
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "year", type: :quantitative)
|> VegaLite.encode_field(:y, "value", type: :quantitative)
|> VegaLite.encode_field(:color, "label", type: :nominal)
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()

Kino.DataTable.new(oita_city_population_composition_df)
VegaLite.new(width: 700, height: 400, title: "大分市人口構成推移")
|> VegaLite.data_from_values(oita_city_population_composition_df,
  only: ["year", "value", "label"]
)
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "year", type: :quantitative)
|> VegaLite.encode_field(:y, "value", type: :quantitative)
|> VegaLite.encode_field(:color, "label", type: :nominal)