hex mapの決定版になりそうなhexmapr
以前、このような記事を書きました。
ここに書いた通り、私は簡単に六角形の地図を描画できるパッケージを探しています。
今回紹介するのは、前回のhexamapmakerとは別の方法で六角形を作るhexmaprパッケージです。geospatial polygonsを正方形や六角形に変換してくれます。
hexmaprこのパッケージはCRANには登録されていません。利用の際はGitHubからインストールします。
devtools::install_github("sassalley/hexmapr")
使い方
今回は神奈川県を例に、hexmaprを使った可視化をやってみましょう。hexmaprを使った作図の方法をまとめると次のような手順になります。
read_polygons()
などの関数を使い、対象のgeom情報をもったSpatialPolygonDataFrameを作成- 作図する領域(グリッドの数)などを
get_shape_details()
で算出する calculate_cell_size()
で与えたポリゴンデータとget_shape_details()
の情報を元に各ポリゴンのサイズと配置を決定する
library(ggplot2) library(viridis) library(dplyr) library(hexmapr)
まずは神奈川県のshapefileを国土数値情報の行政区域データ (平成28年)より取得することにします。ウェブからファイルをダウンロードしても良いのですが、ここではkokudosuuchiを利用してダウンロード先のURLを取得し、Rからファイルのダウンロード、圧縮ファイルの解凍を済ませます。
file.url <- kokudosuuchi::getKSJURL(identifier = "N03", prefCode = 14) %>% arrange(desc(year)) %>% slice(1L) %>% use_series(zipFileUrl) download.file(file.url, destfile = basename(file.url)) unzip(basename(file.url))
original_shapes <- read_polygons("N03-17_14_170101.shp")
original_details <- get_shape_details(original_shapes) original_details$nhex # [1] 1292 new_cells_hex <- calculate_cell_size(original_shapes, original_details, learning_rate = 0.03, grid_type = "hexagonal", seed = 72)
plot(new_cells_hex[[2]])
calculate_cell_size()
は引数seedをもっています。これはポリゴンの算出に乱数を利用しているためで、乱数の値によりピリゴンの配置が異なるようになっています。そのため開発者は乱数を変えて、望ましい図を得ることを推奨しています。次のように良い感じの出力が得られる乱数を特定しておくと良いでしょう。
par(mfrow = c(2, 3), mar = c(0, 0, 2, 0)) for (i in 1:6){ new_cells <- calculate_cell_size(original_shapes, original_details,0.03, "hexagonal", i) plot(new_cells[[2]], main = paste("Seed", i)) }
上の例では、個人的にseed 5の結果を推したいところです。
sfオブジェクトから作成する場合
先ほど用いたhexmaprのread_polygons()
はsfパッケージの読み込み関数をラップしているのですが、出力されるオブジェクトはSpatialPolygonsDataFrameオブジェクトです。sfオブジェクトからhexmaprを利用するには、この形式に変換する必要があります。
以下は既存のsfオブジェクトを利用したいという時のコードです。といっても、as
を使って変換するだけです。
sf.pref14 <- st_read("N03-17_14_170101.shp", options = c("ENCODING=CP932"))
original_shapes <- sf.pref14 %>% as("Spatial")
残りのcalculate_cell_size()
以下は先ほどと同じです。今度はhexではなくregular gridで作図してみましょう。
new_cells <- calculate_cell_size(original_shapes, original_details, 0.03, "regular", 5)
plot(new_cells[[2]])
一つの市区町村で一つのポリゴンに限定する
これまでの神奈川県を例にしたhexmaprによる出力では、市区町村のポリゴンごとに一つの六角形あるいは四角形を生成する、というものでした。なので、飛び地や島を含んだ市区町村は複数行にまたがって記録されるということになっています。
POLYGONをMULTIPOLYGONに変換することで対応します(これがベストな方法なのかは不安なところ)。
sf.pref14 %<>% mutate(city_name = paste( if_else(is.na(N03_003), "", paste(N03_003)), N03_004 )) sf.pref14 %>% # 市区町村ごとにポリゴンを結合する # (複数のPOLYGONをMULTIPOLYGONにする) group_by(city_name) %>% do(out = st_union(.) %>% st_buffer(dist = 0.0001)) -> df.tmp original_shapes <- df.tmp$out %>% purrr::reduce(c) %>% st_sf() original_shapes$city_name <- as.character(df.tmp$city_name) original_shapes %<>% mutate(area = st_area(.)) original_shapes %<>% as("Spatial") original_details <- get_shape_details(original_shapes) new_cells_hex <- calculate_cell_size(original_shapes, original_details, learning_rate = 0.03, grid_type = "hexagonal", seed = 5)
plot(new_cells_hex[[2]])
ggplot2による可視化
# 可視化のために利用 # 別な方法がありそうな shp_clean <- function(shape){ shape@data$id = rownames(shape@data) shape.points = ggplot2::fortify(shape, region = "id") shape.df = plyr::join(shape.points, shape@data, by = "id") }
result_df_hex <- assign_polygons(original_shapes, new_cells_hex) %>% shp_clean()
# quartzFonts(YuGo = quartzFont(rep("IPAexGothic", 4))) # theme_set(theme_gray(base_size = 12, base_family = "IPAexGothic")) ggplot(result_df_hex) + # 市区町村の面積に応じて色付けを行う geom_polygon(aes(x = long, y = lat, fill = as.numeric(area), group = group)) + geom_text(aes(V1, V2, label = city_name), size = 0.8, color = "white", family = "IPAexGothic") + coord_equal() + scale_fill_viridis() + guides(fill = FALSE)
なんだかんだで結構しんどいのでした...
Enjoy!