• このセクションで使う R パッケージ一覧
library(geofacet)
library(ggrepel)
library(rmapshaper)
library(rnaturalearth)
library(sf)
library(tidyverse)
library(zipangu)

1. R で地図を描く過程

  • Rで地図を描く際に必要なのは「地理空間情報」と人口などの「定量データ」

「地理空間情報」の入手先

  • {ggplot2} で地図をプロットする方法は様々
  • ここではパッケージを使ったマッピングについて紹介
  • ここで使うパッケージは次のとおり
パッケージ名 詳細
{rnaturalearth} :Natural Earthのデータ(国や海域の地理空間データを提供)
{rnaturalearthdata} :Natural Earthのデータ(高解像度)

・パッケージ管理ツール (packman パッケージ)を使うと install.packges() コマンドを使わなくてもパッケージをインストールしロードできる

  • {pacman}パッケージの p_load()関数を使って 3 つのパッケージを同時にダウンロードする

packman パッケージを使って 2 つのパッケージをダウンロードする方法

CRANGitHub 上に存在するパッケージを必要に応じてインストールしつつ読み込める
packman パッケージを最初に使うときには初回だけ次のコマンドをコンソールに打ちこむ

install.packages("pacman")
  • 次に、次のコマンドを .Rmd ファイルのチャンクの中に打ち込んで knit する
pacman::p_load(rnaturalearth, rnaturalearthdata)

1. 世界地図  

  • 世界地図を読み込む関数は {naturalearth} が無償で提供する ne_countries() 関数
  • 指定する引数は scaleretunrclass
scale の設定:
  • 解像度が小さい場合 → scale = "small" と指定
  • 解像度が中程度の場合 → scale = "medium" と指定
  • 解像度が大きい場合 → scale = "large" と指定
retunrclass の設定:
  • reutrnclass = "sf" と指定
  • 低解像度の世界地図を sf クラスで読み込んでみる
  • returnclass = "sf" では、地理座標系の sf オブジェクトを指定
  • このように指定することで、地理座標系の sf オブジェクトをマッピングすることができる
world_map <- ne_countries(scale = "small",
                          returnclass = "sf")
  • ダウンロードしたデータ (world_map) の中の変数と型をチェック
class(world_map)
[1] "sf"         "data.frame"
  • クラス(データ形式)は data.framesf の 2 つ
  • world_map のクラスがdata.frame あること
    自分で構築したデータフレームと紐付けして地図をマッピングできる
  • world_map が含む変数名とその数をチェック
names(world_map)
  [1] "featurecla" "scalerank"  "labelrank"  "sovereignt" "sov_a3"    
  [6] "adm0_dif"   "level"      "type"       "tlc"        "admin"     
 [11] "adm0_a3"    "geou_dif"   "geounit"    "gu_a3"      "su_dif"    
 [16] "subunit"    "su_a3"      "brk_diff"   "name"       "name_long" 
 [21] "brk_a3"     "brk_name"   "brk_group"  "abbrev"     "postal"    
 [26] "formal_en"  "formal_fr"  "name_ciawf" "note_adm0"  "note_brk"  
 [31] "name_sort"  "name_alt"   "mapcolor7"  "mapcolor8"  "mapcolor9" 
 [36] "mapcolor13" "pop_est"    "pop_rank"   "pop_year"   "gdp_md"    
 [41] "gdp_year"   "economy"    "income_grp" "fips_10"    "iso_a2"    
 [46] "iso_a2_eh"  "iso_a3"     "iso_a3_eh"  "iso_n3"     "iso_n3_eh" 
 [51] "un_a3"      "wb_a2"      "wb_a3"      "woe_id"     "woe_id_eh" 
 [56] "woe_note"   "adm0_iso"   "adm0_diff"  "adm0_tlc"   "adm0_a3_us"
 [61] "adm0_a3_fr" "adm0_a3_ru" "adm0_a3_es" "adm0_a3_cn" "adm0_a3_tw"
 [66] "adm0_a3_in" "adm0_a3_np" "adm0_a3_pk" "adm0_a3_de" "adm0_a3_gb"
 [71] "adm0_a3_br" "adm0_a3_il" "adm0_a3_ps" "adm0_a3_sa" "adm0_a3_eg"
 [76] "adm0_a3_ma" "adm0_a3_pt" "adm0_a3_ar" "adm0_a3_jp" "adm0_a3_ko"
 [81] "adm0_a3_vn" "adm0_a3_tr" "adm0_a3_id" "adm0_a3_pl" "adm0_a3_gr"
 [86] "adm0_a3_it" "adm0_a3_nl" "adm0_a3_se" "adm0_a3_bd" "adm0_a3_ua"
 [91] "adm0_a3_un" "adm0_a3_wb" "continent"  "region_un"  "subregion" 
 [96] "region_wb"  "name_len"   "long_len"   "abbrev_len" "tiny"      
[101] "homepart"   "min_zoom"   "min_label"  "max_label"  "label_x"   
[106] "label_y"    "ne_id"      "wikidataid" "name_ar"    "name_bn"   
[111] "name_de"    "name_en"    "name_es"    "name_fa"    "name_fr"   
[116] "name_el"    "name_he"    "name_hi"    "name_hu"    "name_id"   
[121] "name_it"    "name_ja"    "name_ko"    "name_nl"    "name_pl"   
[126] "name_pt"    "name_ru"    "name_sv"    "name_tr"    "name_uk"   
[131] "name_ur"    "name_vi"    "name_zh"    "name_zht"   "fclass_iso"
[136] "tlc_diff"   "fclass_tlc" "fclass_us"  "fclass_fr"  "fclass_ru" 
[141] "fclass_es"  "fclass_cn"  "fclass_tw"  "fclass_in"  "fclass_np" 
[146] "fclass_pk"  "fclass_de"  "fclass_gb"  "fclass_br"  "fclass_il" 
[151] "fclass_ps"  "fclass_sa"  "fclass_eg"  "fclass_ma"  "fclass_pt" 
[156] "fclass_ar"  "fclass_jp"  "fclass_ko"  "fclass_vn"  "fclass_tr" 
[161] "fclass_id"  "fclass_pl"  "fclass_gr"  "fclass_it"  "fclass_nl" 
[166] "fclass_se"  "fclass_bd"  "fclass_ua"  "geometry"  
  • 変数の数は 64個
  • 35番目に「各国の人口データ pop_est」があるのでこれを使う   
  • geom_sf() 幾何オブジェクトを使って世界地図を出力してみる
world_map |> 
  ggplot() +
  geom_sf() +
  theme_void() # テーマは「何もない (void)」を選んでみる  

  • 各国の人口に応じて色塗りしてマッピングしてみる
  • world_map のデータ型式が「データフレーム形式」
    pop_est(各国の人口データ)に応じて geom_sf() 内に fill = pop_est でマッピングできる
world_map %>% 
  ggplot() +
  geom_sf(aes(fill = pop_est)) +
  # 人口が少ない国は yellow に、多い国は brown3 色とする
  scale_fill_gradient(low = "yellow", high = "green") +
  labs(fill = "人口") +
  theme_void(base_family = "HiraKakuProN-W3")

  • 中国とインドの人口が飛び抜けて多いことがわかる

1.3 地域を絞った人口規模別地図

アジアの人口規模別地図

  • 世界の一部の地域だけを出力したい場合
  • ne_countries() 内に continent 引数を指定
    → 特定の大陸だけを読み込むことが可能
  • アジアの国のみを抽出し、asia_map という名のオブジェクトとして格納してみる
  • 解像度は中程度に指定
asia_map <- ne_countries(scale = "medium",
                         continent = "Asia",
                         returnclass = "sf")
asia_map |> 
  ggplot() +
  geom_sf() +
  theme_void()

  • この地図を人口に応じて色塗りしてマッピングしてみる
asia_map |> 
  ggplot() +
  geom_sf(aes(fill = pop_est)) +
  scale_fill_gradient(low = "yellow", high = "green") +
  labs(fill = "人口") +
  theme_minimal() +
  theme_void(base_family = "HiraKakuProN-W3")

  • 中国とインドの人口が飛び抜けて多いことがわかるが、アジア諸国の人口の違いがより鮮明になった

東アジアの所得規模別地図

  • ここでは「アジア大陸」から表示規模を「東アジア」に絞って所得規模別地図を描いてみる

  • まず、東アジアにおける各国の所得規模別地図を描いてみる

asia_map <- ne_countries(scale = "medium", 
                         continent = "Asia", 
                         returnclass = "sf")

asia_map %>%
    ggplot() + # 所得グループで色塗り
    geom_sf(aes(fill = income_grp)) +
    theme_void() +
    labs(fill = "Income Group")

  • 表示する対象をアジア大陸から更に「東アジア」に絞りたい場合
    → filter()関数を使って subregion 列を基準に抽出する
asia_map %>%
    filter(subregion == "Eastern Asia") %>% # 「東アジア」に絞る  
    ggplot() +
    geom_sf(aes(fill = income_grp)) +
    theme_void() +
    labs(fill = "Income Group")

  • 東アジアで所得が高いのは日本と韓国、低いのは北朝鮮だとわかる

ヨーロッパ大陸における人口規模別地図

  • 次に、ヨーロッパ大陸だけを出力してみる
europe_map <- ne_countries(scale = "medium",
                           continent = "Europe",
                           returnclass = "sf")
europe_map |> 
  ggplot() +
  geom_sf() +
  theme_void()

  • これだと範囲が広すぎるので coord_sf() 関数で座標系を調整し、ヨーロッパの表示範囲を絞ってみる
    → 経度は -10 度から 45 度まで、緯度は 35 度から 60 度に絞る
    → 経度は xlim で、緯度は ylim で指定
  • 地域を限定して、ヨーロッパ諸国の人口規模を色分けして表示してみる
world_map %>% 
  ggplot() +
  geom_sf(aes(fill = pop_est)) +
  scale_fill_gradient(low = "yellow", high = "green") +
  labs(fill = "人口") +
  coord_sf(xlim = c(-10, 45), ylim = c(35, 60)) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom")

  • ロシアとドイツの人口が多いことは分かるが、このマップからはあまり顕著な違いが分からない

  • 人口を分割している単位をもう少し細分化してみる

world_map2 <- ne_countries(scale = "medium", returnclass = "sf") %>% 
  mutate(Population = case_when(pop_est < 30000000  ~ "3千万未満",
                                pop_est < 40000000  ~ "4千万未満",
                                pop_est < 50000000  ~ "5千万未満",
                                pop_est < 60000000  ~ "6千万未満",
                                pop_est < 70000000  ~ "7千万未満",
                                pop_est < 80000000  ~ "8千万未満",
                                TRUE                ~ "8千万以上"),
         Population = factor(Population, 
                             levels = c("3千万未満", "4千万未満", "5千万未満",
                                        "6千万未満", "7千万未満", "8千万未満",
                                        "8千万以上")))
  • 下のヨーロッパの地図を出力する際には、チャンクオプションに次のように指定すること
{r, fig.width=27, fig.height=27}
world_map2 %>% 
  ggplot() +
  geom_sf(aes(fill = Population)) +
  scale_fill_brewer(palette = "green", drop = FALSE) +
  labs(fill = "人口") +
  coord_sf(xlim = c(-10, 45), ylim = c(35, 60)) +
  geom_label_repel(
    data = st_crop(world_map2,
                   c(xmin = -10, xmax = 45, ymin = 35, ymax = 60)),
    aes(label = name, geometry = geometry),
    size = 11,
    stat = "sf_coordinates",
    min.segment.length = 0
    ) +
  theme_minimal(base_family = "HiraKakuProN-W3") +
  theme(legend.position = "bottom",
        axis.text  = element_text(size = 30),
        legend.title = element_text(size = 32), 
        legend.text = element_text(size = 32),
        legend.key.size = unit(1, "cm"),
        legend.key.width = unit(3,"cm"))

上のマップを描く上での注意 1. R, RStudio, XQuartzを最新版にバージョンアップする
2. 次の手順に従ってパッケージを最新バージョンにアップデートする

パッケージのアップデート方法

Packages をクリック
Update をクリック

・画面左下の Select All をクリック
・画面右下の Install Updates をクリック

  • 国別の具体的な人口を調べたければ
world_map %>% 
  select(sovereignt, pop_est) %>% 
  DT::datatable()

2. 日本地図

2.1 都道府県の人口規模別にマッピング

日本地図を描くために必要な「地理空間情報」の入手先

  • {ggplot2} で地図をプロットする方法は様々
  • ここではパッケージを使ったマッピングについて紹介
  • ここで使うパッケージは次のとおり
パッケージ名 詳細
{rnaturalearth} :Natural Earthのデータ(国や海域の地理空間データを提供)
{rnaturalearthdata} :Natural Earthのデータ(高解像度)

・パッケージ管理ツール (packman パッケージ)を使うと install.packges() コマンドを使わなくてもパッケージをインストールしロードできる

  • {pacman}パッケージの p_load()関数を使って 3 つのパッケージを同時にダウンロードする

packman パッケージを使って 2 つのパッケージをダウンロードする方法

CRANGitHub 上に存在するパッケージを必要に応じてインストールしつつ読み込める
packman パッケージを最初に使うときには初回だけ次のコマンドをコンソールに打ちこむ

install.packages("pacman")
  • 次に、次のコマンドを .Rmd ファイルのチャンクの中に打ち込んで knit する
pacman::p_load(rnaturalearth, rnaturalearthdata)

2.1.1 日本地図データ

  • 日本全土だけを出力したい場合
  • ne_countriescountry 引数を指定する
ne_countries(scale = "small", 
             country = "Japan", 
             returnclass = "sf") %>%
    ggplot() +
    geom_sf() +
    theme_void() 

  • 解像度が悪いので、scale = "medium" と指定してみる
ne_countries(scale = "medium", 
             country = "Japan", 
             returnclass = "sf") %>%
    ggplot() +
    geom_sf() +
    theme_void() 

  • ただ、これだけだとあまり使い道がない
  • 通常、自治体の境界線が必要で、都道府県別の分析が一般的
    → より高解像度の地図が含まれている{rnaturalearthhires}パッケージをインストールし、読み込む
pacman::p_load_gh("ropensci/rnaturalearthhires")

p_load() でなく p_load_gh() を使う理由 ・{rnaturalearthhires}は CRAN に登録されていない(2022年9月2日時点)
GitHubropensciレポジトリーのみで公開
→ {pacman}パッケージの p_load() 関数でなく、p_load_gh()関数を使う

  • 地図データの抽出には ne_states() 関数を使う
  • 第一引数として国家名を指定
  • 地図データのクラスは sf
df_jpn_map <- ne_states("Japan", 
                       returnclass = "sf")

df_jpn_map %>%
  ggplot() +
  geom_sf() +
  theme_void()

  • ne_states() 関数を使って読み込んだ日本地図データ df_jpn_map に都道府県別の人口データは含まれていない
    → 別途、人口データを作り、読み込み、そして「日本地図データ」と「人口データ」をマージする必要がある

2.1.2 都道府県別人口データ(2011年, 2021年)

  • ここでは2022年の「都道府県人口・面積・人口密度ランキングを加工したもの (jpn_pop.csv) を使う

  • csvファイルを読み込むために必要な readr パッケージをロードする
    tidyverse パッケージをロードすると、自動的に readr パッケージもロードされる

  • 都道府県別人口データ (jpn_pop.csv) をダウンロード
    → R プロジェクトフォルダ内に data フォルダを作り、その中に入れる
    RStudio 上で人口データ (jpn_pop.csv) を読み込み、df_jpn_pop と名前をつける

df_jpn_pop <- read_csv("data/jpn_pop.csv", 
                       locale = locale(encoding = "cp932"))
DT::datatable(df_jpn_pop)
  • pop_2016 は2016年10月1日時点での人口
  • pop_2021 は2021年10月1日時点での人口
  • diff は2011年から2021年の間の人口増減率
  • diff の計算式は次のとおり

\[人口増減率= \frac{人口増減(2021年10月−2016年10月)}{2016年10月現在人口}×100\]

2.1.3「地図データ」と「人口データ」のマージ

  • 人口別の日本地図を描くためには「日本地図データ」df_jpn_map と「日本人口データ」 df_jpn_pop を 紐付けるためマージする必要がある
  • それぞれのデータの中身を確認してみる
  • df_jpn_pop の中を確認
DT::datatable(df_jpn_pop)
  • 変数は name, pref, pop_2016,pop_2021, diff の 5 つ
  • df_jpn_map の中を確認
names(df_jpn_map)
  [1] "featurecla" "scalerank"  "adm1_code"  "diss_me"    "iso_3166_2"
  [6] "wikipedia"  "iso_a2"     "adm0_sr"    "name"       "name_alt"  
 [11] "name_local" "type"       "type_en"    "code_local" "code_hasc" 
 [16] "note"       "hasc_maybe" "region"     "region_cod" "provnum_ne"
 [21] "gadm_level" "check_me"   "datarank"   "abbrev"     "postal"    
 [26] "area_sqkm"  "sameascity" "labelrank"  "name_len"   "mapcolor9" 
 [31] "mapcolor13" "fips"       "fips_alt"   "woe_id"     "woe_label" 
 [36] "woe_name"   "latitude"   "longitude"  "sov_a3"     "adm0_a3"   
 [41] "adm0_label" "admin"      "geonunit"   "gu_a3"      "gn_id"     
 [46] "gn_name"    "gns_id"     "gns_name"   "gn_level"   "gn_region" 
 [51] "gn_a1_code" "region_sub" "sub_code"   "gns_level"  "gns_lang"  
 [56] "gns_adm1"   "gns_region" "min_label"  "max_label"  "min_zoom"  
 [61] "wikidataid" "name_ar"    "name_bn"    "name_de"    "name_en"   
 [66] "name_es"    "name_fr"    "name_el"    "name_hi"    "name_hu"   
 [71] "name_id"    "name_it"    "name_ja"    "name_ko"    "name_nl"   
 [76] "name_pl"    "name_pt"    "name_ru"    "name_sv"    "name_tr"   
 [81] "name_vi"    "name_zh"    "ne_id"      "name_he"    "name_uk"   
 [86] "name_ur"    "name_fa"    "name_zht"   "FCLASS_ISO" "FCLASS_US" 
 [91] "FCLASS_FR"  "FCLASS_RU"  "FCLASS_ES"  "FCLASS_CN"  "FCLASS_TW" 
 [96] "FCLASS_IN"  "FCLASS_NP"  "FCLASS_PK"  "FCLASS_DE"  "FCLASS_GB" 
[101] "FCLASS_BR"  "FCLASS_IL"  "FCLASS_PS"  "FCLASS_SA"  "FCLASS_EG" 
[106] "FCLASS_MA"  "FCLASS_PT"  "FCLASS_AR"  "FCLASS_JP"  "FCLASS_KO" 
[111] "FCLASS_VN"  "FCLASS_TR"  "FCLASS_ID"  "FCLASS_PL"  "FCLASS_GR" 
[116] "FCLASS_IT"  "FCLASS_NL"  "FCLASS_SE"  "FCLASS_BD"  "FCLASS_UA" 
[121] "FCLASS_TLC" "geometry"  
  • 84の変数がある
  • 必要な変数だけに絞る
df_jpn_map <- df_jpn_map |> 
  select(name, geometry)
DT::datatable(df_jpn_map)

2 つのデータフレームをマージする際の注意

  • データフレームをマージする際には共通の「変数名」と「値」が必要

人口データ (df_jpn_pop) の name の値を確認

  • unique()関数を使って df_jpn_popname 値を確認してみる
unique(df_jpn_pop$name)
 [1] "Aichi"     "Akita"     "Aomori"    "Chiba"     "Ehime"     "Fukui"    
 [7] "Fukuoka"   "Fukushima" "Gifu"      "Gunma"     "Hiroshima" "Hokkaido" 
[13] "Hyogo"     "Ibaraki"   "Ishikawa"  "Iwate"     "Kagawa"    "Kagoshima"
[19] "Kanagawa"  "Kochi"     "Kumamoto"  "Kyoto"     "Mie"       "Miyagi"   
[25] "Miyazaki"  "Nagano"    "Nagasaki"  "Nara"      "Niigata"   "Oita"     
[31] "Okayama"   "Okinawa"   "Osaka"     "Saga"      "Saitama"   "Shiga"    
[37] "Shimane"   "Shizuoka"  "Tochigi"   "Tokushima" "Tokyo"     "Tottori"  
[43] "Toyama"    "Wakayama"  "Yamagata"  "Yamaguchi" "Yamanashi"

マップデータ (df_jpn_map) の name の値を確認

  • unique()関数をつかって df_jpn_mapname の値を確認してみる
unique(df_jpn_map$name)
 [1] "Kagoshima" "Ōita"      "Fukuoka"   "Saga"      "Nagasaki"  "Kumamoto" 
 [7] "Miyazaki"  "Tokushima" "Kagawa"    "Ehime"     "Kōchi"     "Shimane"  
[13] "Yamaguchi" "Tottori"   "Hyōgo"     "Kyōto"     "Fukui"     "Ishikawa" 
[19] "Toyama"    "Niigata"   "Yamagata"  "Akita"     "Aomori"    "Iwate"    
[25] "Miyagi"    "Fukushima" "Ibaraki"   "Chiba"     "Tokyo"     "Kanagawa" 
[31] "Shizuoka"  "Aichi"     "Mie"       "Wakayama"  "Ōsaka"     "Okayama"  
[37] "Hiroshima" "Hokkaidō"  "Okinawa"   "Gunma"     "Nagano"    "Tochigi"  
[43] "Gifu"      "Shiga"     "Saitama"   "Yamanashi" "Nara"     
  • setdiff()関数を使って、人口データ (df_jpn_pop) の name の値とマップデータ (df_jpn_map) の name の値が同一かどうかチェック
setdiff(df_jpn_map$name, df_jpn_pop$name)
[1] "Ōita"     "Kōchi"    "Hyōgo"    "Kyōto"    "Ōsaka"    "Hokkaidō"
setdiff(df_jpn_pop$name, df_jpn_map$name)
[1] "Hokkaido" "Hyogo"    "Kochi"    "Kyoto"    "Oita"     "Osaka"   
都道府県のローマ字表記が異なるケースが5つある → ローマ字表記を統一する必要あり
  • df_jpn_mapname の値を次のように修正する
    ・Ōita → Oita
    ・Hyōgo → Hyogo
    ・Kyōto → Kyoto
    ・Ōsaka → Osaka
    ・Hokkaidō → Hokkaido
    ・Kōchi → Kochi
df_jpn_map <- df_jpn_map |> 
  mutate(name = str_replace_all(name,
    c("Ōita"      = "Oita",  # "Ōita" を "Oita" に変換
      "Hyōgo"     = "Hyogo", 
      "Kyōto"     = "Kyoto",
      "Ōsaka"     = "Osaka",
      "Hokkaidō"  = "Hokkaido",
      "Kōchi"     = "Kochi")
    ))
  • 再度、setdiff()関数を使って、人口データ (df_jpn_pop) の name の値とマップデータ (df_jpn_map) の name の値が同一かどうかチェック
setdiff(df_jpn_map$name, df_jpn_pop$name)
character(0)
setdiff(df_jpn_pop$name, df_jpn_map$name)
character(0)
  • 2 つのデータフレーム (df_map_popdf_jpn_pop) に共通する変数 name は「変数名」(name) と「値」(Aichi, Akita...) が同じになった
    → マージできる

df_jpn_mapdf_jpn_popname を手がかりにデータをマージして、df_jpn と名前を付ける
・地理データの標準使用に対応するため、マージしたデータは st_as_sf() を使って sfオブジェクト に変換する
- sfパッケージを読み込む

library(sf)
df_jpn <- left_join(df_jpn_pop, df_jpn_map, 
            by = "name") |> 
st_as_sf()

・データフレームを確認する

DT::datatable(df_jpn)  
変数名 説明
1.name 都道府県名(英語)
2.pref 都道府県名(日本語)
3.pop_2016 2016年10月1日時点での人口
4.pop_2021 2021年10月1日時点での人口
5.diff 2011〜2021の人口増減率(%)
6.geometry 地図情報

2.1.4 都道府県人口別に日本地図を描く(2021年)

  • マージしたデータフレーム df_jpn を使って人口の多い都道府県を濃い緑で表示するマップを描いてみる
df_jpn %>%
    ggplot() +
    geom_sf(aes(fill = pop_2021)) +
  scale_fill_distiller(name = "人口",
                       palette = "Greens", # 任意の色を指定
                       direction = 1) + 
    labs(fill = "人口") +
   theme_void(base_family = "HiraginoSans-W3", base_size = 9) +
  ggtitle("都道府県別の人口規模(2021年10月1日)") +
  theme(plot.title = element_text(size = 15)) 

  • 次に、人口規模を 5 つのカテゴリーに順序付き factor 化してから、そのカテゴリーに応じて色塗りをする
  • 適切な値でカテゴリー分けするため、2021年の都道府県別人口データの記述統計を確認する
summary(df_jpn$pop_2021)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
  548562  1057844  1576074  2670279  2670336 14011487 
  • stem() 関数を使って、pop_2021 の分布を確認する
stem(df_jpn$pop_2021, scale = 2)

  The decimal point is 6 digit(s) to the right of the |

   0 | 5777888999
   1 | 01111223333456788999
   2 | 0023689
   3 | 6
   4 | 
   5 | 124
   6 | 3
   7 | 35
   8 | 8
   9 | 2
  10 | 
  11 | 
  12 | 
  13 | 
  14 | 0
  • 300万人以下の都道府県が多い
DT::datatable(df_jpn)
# 人口規模・都道府県別日本地図 (2021)
df_jpn %>%
  mutate(pop_2021a = case_when(pop_2021 >= 8000000 ~ "800万人以上",
                               pop_2021 >= 5000000 ~ "500万人以上",
                               pop_2021 >= 2000000 ~ "200万人以上",
                               pop_2021 >= 1000000 ~ "100万人以上",
                               TRUE            ~ "100万人未満"),
         pop_2021a = factor(pop_2021a, ordered = TRUE,
                           levels = c(
                             "800万人以上", 
                             "500万人以上", 
                             "200万人以上", 
                             "100万人以上", 
                             "100万人未満"))) %>%
  ggplot() +
    geom_sf(aes(fill = pop_2021a)) +
    labs(fill = "人口") +
    theme_void(base_family = "HiraginoSans-W3", base_size = 9) +
  ggtitle("都道府県別 人口規模(2021年10月1日)") +
  theme(plot.title = element_text(size = 15)) 

  • 人口が200万人を超える都道府県は、東北では宮城県(約218万人)、九州では福岡県(約512万人)
  • 人口が100万人以下の都道府県は、東北では秋田県 (94万人)、九州では佐賀県(80万人)

2.1.5 都道府県別の人口増減マップ

  • 都道府県ごとの人口の増減を色で表す
  • 増加を青、減少を赤で表してみる
  • 濃いブルーほど人口が増加率が高く、濃い赤ほど減少率が高い都道府県を示す
# 人口増減・都道府県別日本地図 (2016-2021)
df_jpn %>%
    ggplot() +
    geom_sf(aes(fill = diff)) +
  scale_fill_distiller(name = "人口増減(%)",
                       palette = "RdBu", # 任意の色を指定
                       direction = 1) + 
    labs(fill = "人口") +
   theme_void(base_family = "HiraginoSans-W3", base_size = 9) +
  ggtitle("都道府県別 人口の増減(2016年〜2021年)") +
  theme(plot.title = element_text(size = 15)) 

3. 地図っぽい表現

3.1 人口の増減を時系列で表示させる

  • ここで使う R パッケージ
library(tidyverse)
library(geofacet)
library(zipangu)

人口データ (df_pop)

  • 2008年から2019年までの都道府県別人口データをダウンロードする
board <- pins::board_url(
  c(df_pop = "https://raw.githubusercontent.com/uribo/220828ism_ws/main/df-ssdse-b/data.rds"))
df_pop <-
  board |>
  pins::pin_download("df_pop") |>
  readr::read_rds() 
  • 人口の単位を「人」から「百万人」に変更する
df_pop <- df_pop |> 
  mutate(population = population / 1000000)
  • ダウンロードした人口データを確認する
DT::datatable(df_pop)

グリッド・データ (jp_prefs_grid1)

  • {zipangu}パッケージを使って都道府県情報をダウンロードする
library(zipangu)
jp_prefs_grid1 <-
  jp_prefs_grid1 |>
  left_join(
    jpnprefs |>
      select(jis_code, prefecture = prefecture_kanji),
    by = c("code_pref_jis" = "jis_code"))
DT::datatable(jp_prefs_grid1)

{geofacet}パッケージを使ってグラフを描く

library(geofacet)
plt_1 <- df_pop |>
  ggplot() +
  aes(year, population) +
  geom_line() +
  theme_gray(base_size = 6, 
             base_family = "HiraKakuProN-W3",
             ) +
  facet_geo(~ prefecture,
          grid = "jp_prefs_grid1",
          scales = "free_y") +
  theme(axis.text.x = element_text(angle = 80, # 40度回転
                                   vjust = 1,
                                   hjust = 1)) +
  ggtitle("都道府県別人口の増減(2008-2019)") +
  theme(plot.title = element_text(size = 15)) 

plt_1

・縦軸の最大値が都道府県ごとに異なるので、解釈する際には注意が必要

  • 例えば東京の人口の最大値は約1392万人、鳥取の最大値は約56万人

  • マップの保存

  • fig フォルダを R プロジェクトフォルダ内に作る

  • 作成したマップを fig フォルダに保存する

ggsave("fig/plt_1.png", # 保存したい画像の名前を指定
       plt_1,           # 作成した画像名(オブジェクト名)
       width = 45,      # 画像の横サイズ
       height = 45,    # 画像の縦サイズ
       units = "cm")    # 画像サイズの単位を指定  
                        # インチなら "in"
                        # ミリメートルなら "mm"

3.2 総選挙での自民党得票率を時系列で表示

衆院選データ (df_ldp_vs)

読む込むデータは hr96-21.csv ではないことに注意

hr <- read_csv("data/hr96-21_ken.csv")
  • ダウンロードした衆院選データを確認する
head(hr)
# A tibble: 6 × 23
   year pref  prefecture ku      kun    wl  rank nocand seito     j_name  gender
  <dbl> <chr> <chr>      <chr> <dbl> <dbl> <dbl>  <dbl> <chr>     <chr>   <chr> 
1  1996 愛知  愛知県     aichi     1     1     1      7 新進      河村た… male  
2  1996 愛知  愛知県     aichi     1     0     2      7 自民      今枝敬… male  
3  1996 愛知  愛知県     aichi     1     0     3      7 民主      佐藤泰… male  
4  1996 愛知  愛知県     aichi     1     0     4      7 共産      岩中美… female
5  1996 愛知  愛知県     aichi     1     0     5      7 文化フォ… 伊東マ… female
6  1996 愛知  愛知県     aichi     1     0     6      7 国民党    山田浩  male  
# ℹ 12 more variables: name <chr>, previous <dbl>, age <dbl>, exp <chr>,
#   status <dbl>, vote <dbl>, voteshare <dbl>, eligible <chr>, turnout <chr>,
#   seshu_dummy <chr>, jiban_seshu <chr>, nojiban_seshu <chr>
  • hr96_21_ken.csv は1996年に衆院選挙に小選挙区が導入されて以来実施された 9 回の衆議院選挙(1996, 2000, 2003, 2005, 2009, 2012, 2014, 2017, 2021)の結果のデータ
  • hr に含まれる変数名を表示させる
names(hr)
 [1] "year"          "pref"          "prefecture"    "ku"           
 [5] "kun"           "wl"            "rank"          "nocand"       
 [9] "seito"         "j_name"        "gender"        "name"         
[13] "previous"      "age"           "exp"           "status"       
[17] "vote"          "voteshare"     "eligible"      "turnout"      
[21] "seshu_dummy"   "jiban_seshu"   "nojiban_seshu"
  • hr には 23 個の変数が入っている
変数名 詳細
year 選挙年 (1996-2017)
pref 都道府県名(例:宮城)
prefecture 都道府県名(例:宮城県)
ku 小選挙区名
kun 小選挙区
rank 当選順位
wl 選挙の当落: 1 = 小選挙区当選、2 = 復活当選、0 = 落選
nocand 立候補者数
seito 候補者の所属政党
j_name 候補者の氏名(日本語)
name 候補者の氏名(ローマ字)
previous これまでの当選回数(当該総選挙結果は含まない)
gender 立候補者の性別: “male”, “female”
age 立候補者の年齢
exp 立候補者が使った選挙費用(総務省届け出)
status 候補者のステータス: 0 = 非現職、1 現職、2 = 元職
vote 得票数
voteshare 得票率 (%)
eligible 小選挙区の有権者数
turnout 小選挙区の投票率 (%)
seshu_dummy 世襲候補者ダミー: 1 = 世襲、0 = 非世襲(地盤世襲 or 非世襲)
jiban_seshu 地盤の受け継ぎ元の政治家の氏名と関係
nojiban_seshu 世襲元の政治家の氏名と関係
  • 小選挙区での自民党候補者の得票率 (voteshare) を都道府県 (prefecture) ごとに平均する
df_ldp_vs <- hr |> 
  filter(seito == "自民") |> 
  group_by(year, prefecture) |> 
  summarize(ldp_vs = mean(voteshare))
  • 計算した自民党候補者の得票率の平均を確認する
DT::datatable(df_ldp_vs)

グリッド・データ (jp_prefs_grid1)

  • {zipangu}パッケージを使って、都道府県情報をダウンロードする
jp_prefs_grid1 <-
  jp_prefs_grid1 |>
  left_join(
    zipangu::jpnprefs |>
      select(jis_code, prefecture = prefecture_kanji),
    by = c("code_pref_jis" = "jis_code"))
  • 都道府県情報を確認する
DT::datatable(jp_prefs_grid1)

{geofacet}パッケージを使ってグラフを描く

plt_2 <- df_ldp_vs |>
  ggplot() +
  aes(year, ldp_vs) +
  geom_line() +
  theme_gray(base_size = 6, base_family = "HiraKakuProN-W3") +
  facet_geo(~ prefecture,
          grid = "jp_prefs_grid1",
          scales = "free_y") +
  theme(axis.text.x = element_text(angle = 40, # 40度回転
                                   vjust = 1,
                                   hjust = 1)) +
  ggtitle("総選挙での自民党候補者の得票率平均 (1996-2021)") +
  theme(plot.title = element_text(size = 15)) 
plt_2

・縦軸の最大値が都道府県ごとに異なるので、解釈する際には注意が必要

  • 例えば山口県の最大値は約73%、沖縄の最大値は約21%

  • マップの保存

  • fig フォルダを R プロジェクトフォルダ内に作る

  • 作成したマップを fig フォルダに保存する

ggsave("fig/plt_2.png", # 保存したい画像の名前を指定
       plt_2,           # 作成した画像名(オブジェクト名)
       width = 45,      # 画像の横サイズ
       height = 45,    # 画像の縦サイズ
       units = "cm")    # 画像サイズの単位を指定  
                        # インチなら "in"
                        # ミリメートルなら "mm"

6. Exercise

Q6.1: 「2.1.4 都道府県人口別に日本地図を描く(2021年)」を参考にして、2016年における 都道府県別の人口規模を色分けした日本地図を描きなさい。

Q6.2: 「3.2 総選挙での自民党得票率を時系列で表示」を参考にして、1996年から2021年までの総選挙における、当選者(小選挙区当選者と復活当選者)の平均年齢を都道府県ごとに計算しなさい。

Q6.3: 「3.2 総選挙での自民党得票率を時系列で表示」を参考にして、1996年から2021年までの総選挙における、当選者(小選挙区当選者と復活当選者)の平均年齢を都道府県ごとに「地図っぽい表現」でマッピングし可視化しなさい。

参考文献