• このセクションで使う 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"))