マナティ

Rではじめよう![モダン]なデータ分析

第8回 「新米探偵、データ分析に挑む」の"Rと地図と連携する"をやってみた

「地図との連携方法」と「インターネット上に公開する」方法として、Shinyというパッケージを用いたアプリケーションで作成する手法についてご説明します。

59408_ext_14_0.jpg

はじめに

Rは年々便利になっており、データの取得から結果の公開まですべてRで完結することができます。

『新米探偵、データ分析に挑む』の第6章235ページにおいて、Rの操作に慣れてきた俵太くんが、 Rに地図と連携する機能がある、また、それをそのままスライドとしてインターネットに公開することができる、ということを見つけるシーンがあります。 作中には、その具体的な方法は書かれていませんでした。 今回は、「地図との連携方法」と「インターネット上に公開する」方法として、Shinyというパッケージを用いたアプリケーションで作成する手法について説明したいと思います。

「スライドとして公開する」方法としては、RMarkdownを使う方法が非常に便利です。 日本語の書籍やウェブページも多いので、是非検索してみてください。

以下は、このような流れで話を進めていきたいと思います。

1. データの取得
2. データの加工
3. 描画
4. アプリケーションの作成

1. データの取得

政府統計の総合窓口にある、国勢調査のデータを用います。 csv形式でダウンロードする方法もありますが、今回はAPIを使用してデータを取得する方法を用います。 政府統計の総合窓口(e-Stat) API機能から利用します。

「利用登録・ログイン」から利用登録をし、「ログイン」画面内にある「アプリケーションIDの取得」から、「appID」という英数字の文字列を取得します。

ここからRを使用します。

今回使用するパッケージとその大まかな用途は以下のとおりです。 すべてCRANにあるパッケージなので、ダウンロードしていない場合は以下のコマンドで取得できます。

# 今回使用するパッケージ
install.packages("estatapi") # 政府統計からデータを取得する用
install.packages("dplyr")    # データ加工用
install.packages("tidyr")    # データ加工用
install.packages("ggmap")    # 住所・緯度経度対応用
install.packages("leaflet")  # プロット用

# ダウンロードしたらパッケージの読み込み
library(estatapi)
library(dplyr)
library(tidyr)
library(ggmap) # 住所・緯度経度対応用
library(leaflet) # プロット用

estatapiパッケージの詳しい使い方は
* estatapi - 政府統計の総合窓口(e-Stat)のAPIを使うためのRパッケージ
* Rで解析:政府統計の総合窓口(e-Stat)データ取得に便利です!「estatapi」パッケージ

などを参考にしてください。今回は簡単に説明します。

パッケージを読み込んだら、先ほど取得したappIDをRにも置きます。

> パッケージの読み込み
> library(estatapi)

> # API使用のためのID
> AppID <- "取得したID"

今回は平成22年の国勢調査のデータを使っていきます。 平成22年の国勢調査の調査結果になにがあるのかを調べます。

> # 「平成22年国勢調査」のデータに何があるのかを調べる
> ResultData <- estat_getStatsList(appId = AppID, searchWord = "平成22年国勢調査")
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   356 obs. of  11 variables:
 $ @id                 : chr  "0003033021" "0003033022" "0003033023" "0003033024" ...
 $ @code               : chr  "01" "01" "01" "01" ...
 $ $                   : chr  "人口" "人口" "人口" "人口" ...
 $ STATISTICS_NAME     : chr  "平成22年国勢調査 速報集計 抽出速報集計" "平成22年国勢調査 速報集計 抽出速報集計" "平成22年国勢調査 速報集計 抽出速報集計" "平成22年国勢調査 速報集計 抽出速報集計" ...
 $ @no                 : chr  "00110" "00120" "00210" "00220" ...
 $ CYCLE               : chr  "-" "-" "-" "-" ...
 $ SURVEY_DATE         : chr  "201010" "201010" "201010" "201010" ...
 $ OPEN_DATE           : chr  "2011-06-29" "2011-06-29" "2011-06-29" "2011-06-29" ...
 $ SMALL_AREA          : chr  "0" "0" "0" "0" ...
 $ OVERALL_TOTAL_NUMBER: chr  "1980" "38700" "7776" "75810" ...
 $ UPDATED_DATE        : chr  "2011-08-02" "2011-08-02" "2011-06-29" "2011-06-29" ...

> ResultData %>% as.data.frame() %>% head() # 頭6行を見る
          @id @code    $                        STATISTICS_NAME   @no CYCLE
 1 0003033021    01 人口 平成22年国勢調査 速報集計 抽出速報集計 00110     -
 2 0003033022    01 人口 平成22年国勢調査 速報集計 抽出速報集計 00120     -
 3 0003033023    01 人口 平成22年国勢調査 速報集計 抽出速報集計 00210     -
 4 0003033024    01 人口 平成22年国勢調査 速報集計 抽出速報集計 00220     -
 5 0003033025    01 人口 平成22年国勢調査 速報集計 抽出速報集計 00310     -
 6 0003033026    01 人口 平成22年国勢調査 速報集計 抽出速報集計 00320     -
   SURVEY_DATE  OPEN_DATE SMALL_AREA OVERALL_TOTAL_NUMBER UPDATED_DATE
 1      201010 2011-06-29          0                 1980   2011-08-02
 2      201010 2011-06-29          0                38700   2011-08-02
 3      201010 2011-06-29          0                 7776   2011-06-29
 4      201010 2011-06-29          0                75810   2011-06-29
 5      201010 2011-06-29          0                15390   2011-06-29
 6      201010 2011-06-29          0                 7182   2011-06-29

estatapiパッケージのestat_getStatsList()で、平成22年の国勢調査の調査結果一覧が得られました。 「STATISTICS_NAME」がその調査結果名で、一番右の「@id」がそれに対応するIDです。 今回はIDが0003038591の調査結果を用いることにします。各都道府県の年齢層別の人口です。

> # 今回はIDが0003038591の調査結果を用いる
> # メタ情報を取得
> MetaInfo <- estat_getMetaInfo(appId = AppID, statsDataId = "0003038591")
>
> # データの取得
> PrefData <- estat_getStatsData(appId = AppID,
+                                statsDataId = "0003038591",
+                                cdCat01 = "00710",
+                                cdCat02 = "000",
+                                cdCat04 = "000",
+                                cdCat05 = "000",
+                                lvArea = 2)
> # 中身をチェック
> PrefData %>% str()
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   1081 obs. of  19 variables:
 $ @tab      : chr  "020" "020" "020" "020" ...
 $ @cat01    : chr  "00710" "00710" "00710" "00710" ...
 $ @cat02    : chr  "000" "000" "000" "000" ...
 $ @cat03    : chr  "000" "000" "000" "000" ...
 $ @cat04    : chr  "000" "000" "000" "000" ...
 $ @cat05    : chr  "000" "000" "000" "000" ...
 $ @area     : chr  "01000" "02000" "03000" "04000" ...
 $ @time     : chr  "2010000000" "2010000000" "2010000000" "2010000000" ...
 $ @unit     : chr  "人" "人" "人" "人" ...
 $ $         : chr  "5506419" "1373339" "1330147" "2348165" ...
 $ value     : num  5506419 1373339 1330147 2348165 1085997 ...
 $ tab_info  : chr  "人口" "人口" "人口" "人口" ...
 $ cat01_info: chr  "全域" "全域" "全域" "全域" ...
 $ cat02_info: chr  "総数(男女別)" "総数(男女別)" "総数(男女別)" "総数(男女別)" ...
 $ cat03_info: chr  "総数(年齢)" "総数(年齢)" "総数(年齢)" "総数(年齢)" ...
 $ cat04_info: chr  "総数(国籍)" "総数(国籍)" "総数(国籍)" "総数(国籍)" ...
 $ cat05_info: chr  "総数(出生の月)" "総数(出生の月)" "総数(出生の月)" "総数(出生の月)" ...
 $ area_info : chr  "北海道" "青森県" "岩手県" "宮城県" ...
 $ time_info : chr  "2010年" "2010年" "2010年" "2010年" ...
>
> PrefData %>% as.data.frame() %>% head()
  @tab @cat01 @cat02 @cat03 @cat04 @cat05 @area      @time @unit       $   value
1  020  00710    000    000    000    000 01000 2010000000    人 5506419 5506419
2  020  00710    000    000    000    000 02000 2010000000    人 1373339 1373339
3  020  00710    000    000    000    000 03000 2010000000    人 1330147 1330147
4  020  00710    000    000    000    000 04000 2010000000    人 2348165 2348165
5  020  00710    000    000    000    000 05000 2010000000    人 1085997 1085997
6  020  00710    000    000    000    000 06000 2010000000    人 1168924 1168924
  tab_info cat01_info     cat02_info   cat03_info   cat04_info       cat05_info
1     人口       全域 総数(男女別) 総数(年齢) 総数(国籍) 総数(出生の月)
2     人口       全域 総数(男女別) 総数(年齢) 総数(国籍) 総数(出生の月)
3     人口       全域 総数(男女別) 総数(年齢) 総数(国籍) 総数(出生の月)
4     人口       全域 総数(男女別) 総数(年齢) 総数(国籍) 総数(出生の月)
5     人口       全域 総数(男女別) 総数(年齢) 総数(国籍) 総数(出生の月)
6     人口       全域 総数(男女別) 総数(年齢) 総数(国籍) 総数(出生の月)
  area_info time_info
1    北海道    2010年
2    青森県    2010年
3    岩手県    2010年
4    宮城県    2010年
5    秋田県    2010年
6    山形県    2010年

> # 年齢層
> ages <- PrefData$cat03_info %>% unique()
> ages
 [1] "総数(年齢)" "0~4歳"       "5~9歳"       "10~14歳"     "15~19歳"
 [6] "20~24歳"     "25~29歳"     "30~34歳"     "35~39歳"     "40~44歳"
[11] "45~49歳"     "50~54歳"     "55~59歳"     "60~64歳"     "65~69歳"
[16] "70~74歳"     "75~79歳"     "80~84歳"     "85~89歳"     "90~94歳"
[21] "95~99歳"     "100歳以上"    "不詳"

説明が駆け足になりましたが、ここまでがデータの取得です。 最初にも書きましたが、csvをダウンロードする方法もありますので、 この方法が面倒だと感じたらそちらの方法でも良いでしょう。

2. データの加工

上で取得したデータを、地図上でプロットするために加工していきます。 まずは、行に都道府県、列に年齢層が並ぶデータを作るために、dplyrパッケージ、tidyrパッケージを駆使します。

> library(dplyr)
> library(tidyr)

> # 整形
> Prefdf <- PrefData %>%
+   # 今回用いる列はPrefDataのうち、area_info(都道府県)、cat03_info(年齢層)、value(人口)
+   select(area_info, cat03_info, value) %>%
+   # 行に都道府県、列に年齢層がくるように加工
+   tidyr::spread(key = cat03_info, value = value, fill=NA, convert=FALSE, drop=TRUE) %>%
+   # 「area_info」を「都道府県」に名称変更
+   rename(都道府県 = area_info) %>%
+   # 列の並ぶ順番を調整
+   select(都道府県, one_of(ages)) %>%
+   # 扱いやすいようにdata.frame型に変更
+   as.data.frame()
>
> # このようなデータになります
> Prefdf %>% str()
'data.frame':   47 obs. of  24 variables:
 $ 都道府県    : chr  "愛知県" "愛媛県" "茨城県" "岡山県" ...
 $ 総数(年齢): num  7410719 1431493 2969770 1945276 1392818 ...
 $ 0~4歳      : num  346338 56508 122330 82489 80792 ...
 $ 5~9歳      : num  353251 61357 134010 88502 81422 ...
 $ 10~14歳    : num  365665 67314 143298 93862 84099 ...
 $ 15~19歳    : num  361670 65646 144480 94662 83477 ...
 $ 20~24歳    : num  403988 58624 145495 97478 76546 ...
 $ 25~29歳    : num  462251 70427 167064 104518 86184 ...
 $ 30~34歳    : num  518107 82870 189035 117606 94733 ...
 $ 35~39歳    : num  618763 97172 221348 140449 105201 ...
 $ 40~44歳    : num  539881 84402 195016 117230 91826 ...
 $ 45~49歳    : num  472604 85099 181718 109577 88611 ...
 $ 50~54歳    : num  413484 89511 186762 113512 91916 ...
 $ 55~59歳    : num  449460 104136 221170 127211 98513 ...
 $ 60~64歳    : num  551237 121104 239613 156250 80953 ...
 $ 65~69歳    : num  464480 94089 193226 128664 58874 ...
 $ 70~74歳    : num  374676 83951 156865 106181 61287 ...
 $ 75~79歳    : num  292728 79119 128216 100233 50514 ...
 $ 80~84歳    : num  197726 63446 99179 77672 35072 ...
 $ 85~89歳    : num  105492 37114 57055 45086 19940 ...
 $ 90~94歳    : num  43148 15562 23178 19806 10400 ...
 $ 95~99歳    : num  12261 4590 6532 6096 3548 ...
 $ 100歳以上   : num  1574 720 814 980 872 ...
 $ 不詳        : num  61935 8732 13366 17212 8038 ...
> Prefdf %>% head()
  都道府県 総数(年齢) 0~4歳 5~9歳 10~14歳 15~19歳 20~24歳 25~29歳 30~34歳
1   愛知県      7410719 346338 353251   365665   361670   403988   462251   518107
2   愛媛県      1431493  56508  61357    67314    65646    58624    70427    82870
3   茨城県      2969770 122330 134010   143298   144480   145495   167064   189035
4   岡山県      1945276  82489  88502    93862    94662    97478   104518   117606
5   沖縄県      1392818  80792  81422    84099    83477    76546    86184    94733
6   岩手県      1330147  49685  56532    62587    64637    54739    63878    74898
  35~39歳 40~44歳 45~49歳 50~54歳 55~59歳 60~64歳 65~69歳 70~74歳 75~79歳
1   618763   539881   472604   413484   449460   551237   464480   374676   292728
2    97172    84402    85099    89511   104136   121104    94089    83951    79119
3   221348   195016   181718   186762   221170   239613   193226   156865   128216
4   140449   117230   109577   113512   127211   156250   128664   106181   100233
5   105201    91826    88611    91916    98513    80953    58874    61287    50514
6    83067    77956    82114    88648   101897   103946    84522    83864    80110
  80~84歳 85~89歳 90~94歳 95~99歳 100歳以上  不詳
1   197726   105492    43148    12261      1574 61935
2    63446    37114    15562     4590       720  8732
3    99179    57055    23178     6532       814 13366
4    77672    45086    19806     6096       980 17212
5    35072    19940    10400     3548       872  8038
6    60973    33193    13636     3699       501  5065

無事、行に都道府県、列に年齢層が並ぶデータができました。

3. 描画

ようやく本番です。 地図上にデータをプロットするために、地点(この例では各都道府県)ごとに緯度と経度を取得する必要があります。 今回はggmapパッケージのgeocode()を使用します。 これは、Google Maps APIを使用して緯度と経度を取得するものです。 APIの利用には制限があるので(1日2500回まで)、使いすぎることのないようにしましょう。

> library(ggmap)
>
> # 各都道府県の緯度経度を手に入れる。API制限に注意
> PrefInfo <- geocode(Prefdf$都道府県, source = "google", output = "latlon")
>
> # lanが経度、latが緯度
> PrefInfo %>% head()
       lon      lat
1 136.9066 35.18019
2 132.7657 33.84162
3 140.4468 36.34181
4 133.9344 34.66175
5 127.6809 26.21240
6 141.1527 39.70362
>
> # 人口データと合体
> PrefMap <- Prefdf %>% cbind(PrefInfo)
> PrefMap %>% head()
  都道府県 総数(年齢) 0~4歳 5~9歳 10~14歳 15~19歳 20~24歳 25~29歳 30~34歳
1   愛知県      7410719 346338 353251   365665   361670   403988   462251   518107
2   愛媛県      1431493  56508  61357    67314    65646    58624    70427    82870
3   茨城県      2969770 122330 134010   143298   144480   145495   167064   189035
4   岡山県      1945276  82489  88502    93862    94662    97478   104518   117606
5   沖縄県      1392818  80792  81422    84099    83477    76546    86184    94733
6   岩手県      1330147  49685  56532    62587    64637    54739    63878    74898
  35~39歳 40~44歳 45~49歳 50~54歳 55~59歳 60~64歳 65~69歳 70~74歳 75~79歳
1   618763   539881   472604   413484   449460   551237   464480   374676   292728
2    97172    84402    85099    89511   104136   121104    94089    83951    79119
3   221348   195016   181718   186762   221170   239613   193226   156865   128216
4   140449   117230   109577   113512   127211   156250   128664   106181   100233
5   105201    91826    88611    91916    98513    80953    58874    61287    50514
6    83067    77956    82114    88648   101897   103946    84522    83864    80110
  80~84歳 85~89歳 90~94歳 95~99歳 100歳以上  不詳      lon      lat
1   197726   105492    43148    12261      1574 61935 136.9066 35.18019
2    63446    37114    15562     4590       720  8732 132.7657 33.84162
3    99179    57055    23178     6532       814 13366 140.4468 36.34181
4    77672    45086    19806     6096       980 17212 133.9344 34.66175
5    35072    19940    10400     3548       872  8038 127.6809 26.21240
6    60973    33193    13636     3699       501  5065 141.1527 39.70362
>
> # PrefMapの列名を変更しておく
> colnames(PrefMap) <- c("都道府県", "総数", ages[-1], "lon", "lat")

これで各都道府県の緯度・経度と人口の情報が得られたので、地図上で表現していきましょう。 今回使用するパッケージはleafletです。 leafletパッケージとは、オープンソースのJavaScriptのライブラリで、地図を描画し、インタラクティブに動かすことのできるものです。Rのleafletパッケージは、これを簡単に呼び出すことができます。

それでは、今回取得したデータについて、まずは各都道府県の人口の総数をプロットしてみましょう。 Rは以下のように書きます。

> # 人口の総数を描画
> leaflet(PrefMap) %>%
+     addTiles() %>%
+     # 中心、ズームサイズを調整
+     setView(lng = 139, lat = 37, zoom = 5) %>%
+     # 人口の総数ごとにプロットサイズを変える
+     addCircles(lng = ~lon, lat = ~lat, weight = 1,
+                radius = ~sqrt(総数) * 30,
+                # プロットをクリックしたら都道府県名と人口の数が表示されるようにする
+                popup = ~paste(都道府県, 総数, sep=": "))

これを実行すると、RStudioを使用している場合「Viewer」の部分にこのような日本地図が表示されるはずです。

img01.png

人口が多いところほど大きな円でプロットされます。また、円をクリックすると都道府県名と人口が表示されます。sqrtとpasteの中身をPrefMapのほかの列に変更するとそれに対応した列を同様にプロットできます。

著者プロフィール

松村杏子(著者)
Web制作ベンチャー企業を経て、2016年4月ヤフー株式会社に入社。インターネット広告の分析に携わる。学生時代の専門は計量経済学とゲーム理論。
匿名知的集団ホクソエム(著者)
ホクソエム (hoxo_m) は架空のデータ分析者であり、日本の若手のデータ分析者集団のペンネームである。当初このデータ分析者集団は秘密結社として活動し、ホクソエムを一個人として活動させ続けた。