都道府県の市区町村を人口で2分割するやつ: 岡山県版

市区町村ごとの人口数によって、都道府県を2分割するというやつをRでやってみる。全国版はあとで

Shinya Uryu

4 minute read

少し前によく見かけたやつ。Rでやってみる。人口データはユタニーの{estatapi}でe-Statから取得する。マッピングは手前味噌ながら、{jpndistrict}パッケージを使うと楽。

必要なパッケージを読み込んで、データを取得、可視化までを行う。

**追記: 全国版

# データ取得・操作
library(estatapi)
library(jpndistrict)
library(magrittr)
library(spdplyr)
library(dplyr)
# library(tidyr)

# 可視化
library(ggplot2)
library(ggrepel)

データの用意

まずはデータを用意する。人口データと地図データを用意する。

人口データ (平成27年国勢調査 人口等基本集計)

estatapi::estat_getStatsList()で「人口」をキーワードにして検索を行う。appIdに与えるe-Statのトークンは各自で取得したものを使う。

d.list <- estat_getStatsList(appId = Sys.getenv("ESTAT_TOKEN"), searchWord = "人口")
nrow(d.list)
## [1] 14380

「人口」で検索すると複数の項目がヒットするのだけど、そこから「平成27年国勢調査 人口等基本集計」のデータを選択する。

d.list %>% filter(`@id` == "0003148500") %>% 
  select(`@id`, STAT_NAME, STATISTICS_NAME, TITLE, SURVEY_DATE)
## # A tibble: 1 × 5
##        `@id` STAT_NAME
##        <chr>     <chr>
## 1 0003148500  国勢調査
## # ... with 3 more variables: STATISTICS_NAME <chr>, TITLE <chr>,
## #   SURVEY_DATE <chr>

# 全国のデータを取得
d.pops <- estat_getStatsData(
  appId = Sys.getenv("ESTAT_TOKEN"),
  statsDataId = "0003148500",
  cdCat01     = c("00710")
)
d.pops %>% head()
## # A tibble: 6 × 10
##   tab_code 表章項目 cat01_code `全域・人口集中地区(2015)` area_code
##      <chr>    <chr>      <chr>                        <chr>     <chr>
## 1      020     人口      00710                         全域     00000
## 2      020     人口      00710                         全域     00001
## 3      020     人口      00710                         全域     00002
## 4      020     人口      00710                         全域     01000
## 5      020     人口      00710                         全域     01001
## 6      020     人口      00710                         全域     01002
## # ... with 5 more variables: `地域(2015)` <chr>, time_code <chr>,
## #   `時間軸(年次)` <chr>, unit <chr>, value <dbl>

データはこんな感じになっている。地域(2015)という列が行政区域の名称で、都道府県全体だったり市区町村だったりする。またそれにともなってarea_codeが割り振られている。人口の値はvalueに記録されている。使いやすいように少し処理を加える。

  1. area_codeの先頭2桁は都道府県コードなので、都道府県のデータを抽出できるようにmutate()で都道府県コードの列を作成する。
  2. 合併前の行政区域でのデータも含まれるため、市町村のデータに限定する(旧行政名は括弧で括られている)。この時、「区」のデータもあるのだが、区が含まれる「市」のデータがあるのでそれを利用するようにする。
  3. 都道府県(1で作成した都道府県コードでgroup_by())ごとに都道府県人口の過半数以上・未満で市町村を区分する。各市町村の人口数を都道府県の総人口で割り、人口数の少ない市町村から累積し、5割以上となる市町村をmajority、5割未満をminorityとして扱う。
d.pops %<>% 
  # 都道府県コードの列を追加
  mutate(pref_code = substr(area_code, 1, 2)) %>% 
  # 市町村のデータを抽出(区は除外する)
  filter(`表章項目` == "人口",
         grepl("(市|町|村)$", `地域(2015)`)) %>% 
  # 必要な列だけを選択
  select(area_code, `地域(2015)`, value, pref_code) %>% 
  group_by(pref_code) %>% 
  do(aaa = arrange(., value) %>% 
       mutate(sum_value = value / sum(value),
         harf      = cumsum(sum_value)) %>% 
  mutate(type = if_else(harf < 0.50, "minority", "majority"),
         type = ifelse(is.na(type), "minority", type)) %>% 
    select(-pref_code)) %>% 
  tidyr::unnest()

地図データ

国土数値情報の行政区域 平成27年4月1日時点のデータ http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03.html を利用してSpatialPolygonDataframeを作成する。ここでも区は市にまとめ、行政コードも市のものを採用するという処理をする。

d33 <- spdf_jpn_pref(code = 33, district = TRUE) %>% 
  mutate(city_name = if_else(grepl("区$", city_name_full), city_name_, city_name),
                    city_code = ifelse(grepl("区$", city_name_full), 
                                         paste0(substr(city_code, 1, 3), "00"),
         as.character(city_code))) %>% 
  select(city_name, city_code)

行政名ラベルと位置データ(市区町村役場データ)

地図を作る際、市区町村ごとにラベルをふりたいので用意する。jpndistrict::spdf_jpn_admins()により、国土数値情報 市区町村役場データ http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-P34.html からデータをダウンロードする(すでにShapefileがあればpath引数でディレクトリを指定)

d.admin33 <- spdf_jpn_admins(code = 33) %>% 
      dplyr::mutate(name = gsub("(役所|役場|役場(移転中))$", "", name)) %>% 
  dplyr::filter(type == 1, !grepl("区$", name)) 

プロット

あらかじめ、地図データを{ggplot2}ベースの地図として描画するためにggplot2::fortify()にかけ、人口データと結合させておく。あとはgeom_mapでデータをのせるだけ。

d.map <- d33 %>% 
    ggplot2::fortify(region = "city_code") %>% 
    dplyr::left_join(d.pops, by = c("id" = "area_code"))
p <- ggplot() +
  geom_map(data = d.map,
           map = d.map,
           aes(x = long, y = lat, group = group, map_id = id, fill = type),
           color = "#FFFFFF", size = 0.1) + 
  coord_map() +
  ggthemes::theme_map(base_size = 12, base_family = "YuGo") +
    guides(fill = FALSE)

ラベルは{ggrepel}の関数を使うとよしなに位置を調整してくれるので便利。

# family は適当に変更
p <- p + geom_point(data = [email protected], aes(x = longitude, y = latitude)) +
      ggrepel::geom_text_repel(data = [email protected], 
                               aes(longitude, latitude, label = name, family = "IPAexGothic"))

岡山、倉敷論争に終止符が打たれる日はいつになるやら。

comments powered by Disqus