市区町村ポリゴンの中から区だけを結合する
前回の記事で、市区町村に分割されているポリゴンを都道府県単位に結合する処理を紹介しました。
今日はその続編として、今度は区ごとにポリゴンが分かれている「政令指定都市」を一つの市として扱えるようにしてみようと思います。これは、例えば市町村単位のデータと市区町村のポリゴンを紐づけようとする際、つまりデータ間で政令指定都市の扱いが異なる時に役立つtipsです。 なお、ポリゴンの方が細かい、すなわち政令指定都市が「区」に分かれていて紐づけるデータの方が「市」であることを想定しています。
20180913追記✍️ ポリゴンに不備がない場合には、group_by(city) %>% summarise() のようにするだけで良いです。 id:yutannihilation さんからのツッコミ。いつもありがとう🙏
岡山県を例に区の結合処理を扱います。このデータは、city_code
列に市区町村コード、city
列に市区町村名を含んでいます。問題の政令指定都市には「hoge市piyo区」の形式が与えられています。
📔 この記事の中で利用したポリゴンデータは、国土地理院長の承認を得て、同院発行の数値地図(国土基本情報)電子国土基本図(地図情報)を使用し、瓜生真也が加工・編集したものです (承認番号 平28情使、第603号)
library(tidyverse) # dplyr, stringr, tidyr, purrrパッケージの関数を利用します library(sf) library(mapview)
library(jpndistrict)
## This package provide map data is based on the Digital Map 25000 ## (Map Image) published by Geospatial Information Authority of Japan ## (Approval No.603FY2017 information usage <http://www.gsi.go.jp>)
sf_pref33 <- jpn_pref(33, district = TRUE) sf_pref33
## Simple feature collection with 30 features and 4 fields ## geometry type: GEOMETRY ## dimension: XY ## bbox: xmin: 133.2667 ymin: 34.29839 xmax: 134.4132 ymax: 35.35286 ## epsg (SRID): 4326 ## proj4string: +proj=longlat +datum=WGS84 +no_defs ## # A tibble: 30 x 5 ## pref_code prefecture city_code city geometry ## <chr> <chr> <chr> <chr> <GEOMETRY [°]> ## 1 33 岡山県 33101 岡山市 北区… POLYGON ((133.9098 34.948, 133.… ## 2 33 岡山県 33102 岡山市 中区… MULTIPOLYGON (((133.9747 34.601… ## 3 33 岡山県 33103 岡山市 東区… MULTIPOLYGON (((133.9958 34.613… ## 4 33 岡山県 33104 岡山市 南区… MULTIPOLYGON (((133.9109 34.643… ## 5 33 岡山県 33202 倉敷市 MULTIPOLYGON (((133.6414 34.504… ## 6 33 岡山県 33203 津山市 POLYGON ((134.0871 35.30721, 13… ## 7 33 岡山県 33204 玉野市 MULTIPOLYGON (((133.8985 34.456… ## 8 33 岡山県 33205 笠岡市 MULTIPOLYGON (((133.5929 34.373… ## 9 33 岡山県 33207 井原市 POLYGON ((133.3705 34.74212, 13… ## 10 33 岡山県 33208 総社市 POLYGON ((133.6613 34.78109, 13… ## # ... with 20 more rows
岡山県の県庁所在地である岡山市は2009年に政令指定都市へ移行し、北区、中区、東区、南区の4つの区からなります。
sf_pref33 %>% filter(str_detect(city, "^岡山市")) %>% mapview()
4区を一つのポリゴンに結合するには前回書いた方法を使えばできます。ただし今回は、政令指定都市でない他の市町村に関してはその形状を保持するという制約がつきます。
そんなん簡単やろー、と思いましたが結構悩みました。以下に解決策を示しますが、あまりスマートな方法とは思えないのでお助け募集です。また、市区町村コードに関しては政令指定都市の場合には原則として100番台の値から始まりますが、例外もあり、市で表記した時の扱いもまちまちだったので以降の処理では除外しています。
まずは市区町村の形状を保ったままcity
の値を変えます。下記の正規表現による文字列置換を適用しました。
sf_pref33 <- sf_pref33 %>% mutate(city = str_remove(city, "[[:space:]].+区$"))
この処理により、「hoge市piyo区」が「hoge市」になります。その後、city
の値ごとにグループ化し、tidyr::nest()
により、市町村ごとのポリゴンを格納した入れ子データフレームを作成します。
sf_pref33 <- sf_pref33 %>% group_by(city) %>% nest()
入れ子の中には、岡山市のようにもともと複数のポリゴンを含む場合には複数行のデータフレームが格納されています。その他の市町村については一つです。この入れ子のポリゴンデータに対して、複数ポリゴンを隙間なく結合する処理を関数化したものを適用します。
city_union <- function(x) { x %>% lwgeom::st_make_valid() %>% sf::st_union(by_feature = FALSE) %>% sf::st_transform(crs = 4326) %>% sf::st_cast("POLYGON") %>% purrr::map( ~ .x[1] ) %>% sf::st_multipolygon() %>% sf::st_sfc(crs = 4326) }
sf_pref33 <- sf_pref33 %>% transmute(city, geometry = pmap(., ~ city_union(..2)) %>% reduce(c)) %>% st_sf()
では確認します。
sf_pref33 %>% mapview()
できました!岡山市の各区の境界がなくなり、一つのポリゴンとして扱えるようになっています。また、ポリゴンの空隙もありません。綺麗なポリゴンになっています。
というわけでEnjoy!