★データ解析備忘録★

ゆる〜い技術メモ

Rで欲しい県について国勢調査 小地域 Shapefile を全部ダウンロードする

はじめに

先日、国勢調査 小地域 Shapefileからより細かい粒度で逆ジオコーディングを行う方法を書きました。

y-mattu.hatenablog.com

しかし、ここで使っていた小地域shapefileをダウンロードをする関数では県と市をこちらで指定する必要がありました。(uriさんのコードではleafletへのプロットまで行っていますが、ダウンロードして解凍するだけの関数をこちらのgistにあげています。)

download_smallshape(pref = "33", city = "倉敷市")

さらに厄介なことに、ここで指定する市の名前の形は都道府県によってはやや特殊です。

例えば埼玉県 f:id:songcunyouzai:20170728161505p:plain

例えば北海道 f:id:songcunyouzai:20170728161555p:plain

ここの指定を一文字でも間違えると、正しくダウンロードされません。

そこで、このページの状態でこの市や町の名前をスクレイピングで取得することを考えます。

関数

そうして書いた関数が all_cities() という関数です。引数は県の番号(の文字列)ですが、後述するようにこれも県名から自動で取得できます。

library(RSelenium)
library(rvest)
library(sf)
library(magrittr)
library(tidyverse)
library(stringr)

all_cities <- function (pref) {
  rD <- rsDriver(verbose = FALSE)
  remDr <- rD[["client"]]
  
  remDr$navigate("http://e-stat.go.jp/SG2/eStatGIS/page/download.html")
  
  # 国勢調査を選択
  webElem <- remDr$findElement("css selector", "#censusclass_list")
  childElems <- webElem$findChildElements("css selector", "#censusclass_list > option")
  childElems[[2]]$clickElement()
  
  # 平成27年国勢調査 (小地域)
  Sys.sleep(3)
  childElems <- remDr$findElement("css selector", "#census_list > option:nth-child(1)")
  childElems$clickElement()
  Sys.sleep(3)
  x <- remDr$findElement("css selector", "#step2_T000849")
  # x <- remDr$findElement("xpath", '//*[@id="step2_label_T000849"]')
  x$clickElement()
  Sys.sleep(3)
  
  # ダウンロードページへ遷移
  childElems <- remDr$findElement("css selector", "#page1 > div.main-action > p > input.button-important.long")
  childElems$clickElement()
  Sys.sleep(3)
  childElems2 <- remDr$findElement("css selector",
                                   paste0("#pref_list > option:nth-child(", select_pref(pref) %>%
                                            magrittr::use_series(code) %>% as.numeric(), ")"))
  childElems2$clickElement()
  Sys.sleep(3)
  childElems3 <- remDr$findElements("css selector", "#city_list > option")
  
  # 現在のページをスクレイピング
  out <- remDr$getPageSource(header = TRUE)
  
  # seleniumサーバーをストップ
  remDr$close()
  rD[["server"]]$stop()
  
  # 市町村リストを作成
  city_list <- read_html(out[[1]], encoding = "utf8") %>%
    html_node(xpath = "//*[@id='step3']/div/div[2]/table/tbody/tr[3]") %>%
    html_text() %>%
    str_replace_all("\n", "") %>%
    str_replace_all("\t", "") %>%
    str_replace_all("\\d", "") %>%
    str_split(" ") %>%
    unlist() %>%
    str_subset("")
  
  return(city_list)
}

使い方

使い方ですが、引数は県の番号(の文字列)です。例えば埼玉県であれば、 "11" を入力値として、Seleniumでブラウザを自動操作し、市町村のリストを文字列ベクトルで作成してくれます。

saitama <- all_cities("11")

saitama
#>  [1] "さいたま市西区"   "さいたま市北区"   "さいたま市大宮区"
#>  [4] "さいたま市見沼区" "さいたま市中央区" "さいたま市桜区"  
#>  [7] "さいたま市浦和区" "さいたま市南区"   "さいたま市緑区"  
#> [10] "さいたま市岩槻区" "川越市"           "熊谷市"          
#> [13] "川口市"           "行田市"           "秩父市"          
#> [16] "所沢市"           "飯能市"           "加須市"          
#> [19] "本庄市"           "東松山市"         "春日部市"        
#> [22] "狭山市"           "羽生市"           "鴻巣市"          
#> [25] "深谷市"           "上尾市"           "草加市"          
#> [28] "越谷市"           "蕨市"             "戸田市"          
#> [31] "入間市"           "朝霞市"           "志木市"          
#> [34] "和光市"           "新座市"           "桶川市"          
#> [37] "久喜市"           "北本市"           "八潮市"          
#> [40] "富士見市"         "三郷市"           "蓮田市"          
#> [43] "坂戸市"           "幸手市"           "鶴ヶ島市"        
#> [46] "日高市"           "吉川市"           "ふじみ野市"      
#> [49] "白岡市"           "北足立郡伊奈町"   "入間郡三芳町"    
#> [52] "入間郡毛呂山町"   "入間郡越生町"     "比企郡滑川町"    
#> [55] "比企郡嵐山町"     "比企郡小川町"     "比企郡川島町"    
#> [58] "比企郡吉見町"     "比企郡鳩山町"     "比企郡ときがわ町"
#> [61] "秩父郡横瀬町"     "秩父郡皆野町"     "秩父郡長瀞町"    
#> [64] "秩父郡小鹿野町"   "秩父郡東秩父村"   "児玉郡美里町"    
#> [67] "児玉郡神川町"     "児玉郡上里町"     "大里郡寄居町"    
#> [70] "南埼玉郡宮代町"   "北葛飾郡杉戸町"   "北葛飾郡松伏町"  

これの一つ一つを download_smaklshape() に入れていけばいいわけです。

for (i in 1:length(saitama)) {
  download_smallshape(saitama[i])
}

県名だけで一気にダウンロードしたい

いくつかの県についてこれをやるときは、県名で一気にやりたくなります。 例えば11個の都道府県であれば、まずは市町村名の取得として、

# 必要な県
prefs <- c('福島県', '茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県','山梨県', '長野県', '静岡県')
# 必要な県(番号)
prefnums <- jpndistrict::jpnprefs %>%
  filter(prefecture %in% prefs) %>%
  pull(jis_code)

# 件ごとの市リスト
city_list <- list()
for (i in 1:length(prefnums)) {
  city_list[[i]] <- all_cities(prefnums[i])
  names(city_list[[i]]) <- prefs[i]
  Sys.sleep(3)
}

これで、欲しい県について以下のような市区町村リストが出来上がります。 f:id:songcunyouzai:20170728165402p:plain あとはダウンロードするだけです。

# ダウンロード #
for (j in 1:length(prefnums)) {
  for (k in 1:(length(city_list[[j]][k]))) {
    download_smallshape(pref = prefnums[j], city = city_list[[j]][k])
    Sys.sleep(180)
  }
}

ただ、これだと数百個のshapefileがダウンロードされて大変なことになるので、 どこかで読み込みや.RDataでの保存をやっておいたほうがいいと思います。 また、e-statがうまく読み込めずエラーになることが多いので全部まとめてやらずに例えば県ごとなど、ループを小分けにしてやったほうが良いです。