はじめに
これまでRはちょっと難しそうだなと感じがしていて、複雑な統計計算以外には使っていなかったのですが、tidyverseが意外と簡単そうな気がしましたので、最近また使い始めました。なかでも、tidyverseのdplyrパッケージにあるgroup_nestが便利そうなのですが、使い方がよくわかりませんでした。
データとして、国土交通省が公開している
これまでに公表した面積調(昭和63年以降)にある「令和元年7月以降(令和2年7月まで)[CSV:154KB]」を読み込んで集計してみました。
library(tidyverse)
library(magrittr)
area_data <- read_csv("R1_R2_all_mencho.csv", skip=4, locale=locale(encoding="CP932"))
このファイルのエンコードはCP932になっており、ヘッダの文字に㎡が使われています。
はじめにread.csv("R1_R2_all_mencho.csv", skip=4, fileEncoding="CP932")
で読み込んでみたのですが、㎡がうまく扱えませんでした。
市区町村以外のデータも含まれていましたので、市区町村だけのデータにします。
area_data %<>% select(1,2,4,5) %>% rename(`面積`=starts_with("令和"))
area_data %<>% filter(!is.na(`市区町村`) & !str_detect(`市区町村`, "\\(") & !is.na(`標準地域コード`))
area_data %<>% select(-`標準地域コード`)
都道府県別に集計する
g1 <- area_data %>% group_nest(`都道府県`)
都道府県別にグループ化しています。説明があとになってしまいましたが、ここではRStudioを使っています。g1の表示です。各都道府県が1行になっています。
data列の表アイコンをクリックすると、その都道府県のデータが表示されます。
data列のデータ全体はg1$data
で表示されます。都道府県別に分割されたtibbleのリストです。group_splitと似た形式になっていますが、group_nestでは都道府県が抜けています。
今回は、市町村合併で減少しましたが「村」について集計して見ます。
まず、tibble(またはdata.frame)データから、村だけを取り出す関数を作ってみます。
mura <- function(x){filter(x, str_ends(`市区町村`, "村"))}
「市区町村」で村で終わるものだけを取り出します。グループ化前のarea_dataデータを使って試してみます。
mura(area_data)
村だけが抽出されてることがわかります。
次にgroup_nestされたデータに適用してみます。上に示したg1$data
出力を処理できるようにすると良いのですが、..
purrrにあるmapを使います。map(g1$data, ~mura(.))
とすると村だけに絞り込まれたリストが返されます。
g1 %<>% mutate(`村`=map(data, ~mura(.x)))
g11 <- g1 %>% unnest(`村`) # おまけ
これで「村」列に村だけに絞り込まれたデータが追加され、g11には展開されたデータが入ります。わざわざ関数を作らなくても、無名関数で
g1 %<>% mutate(`村`=map(data, function(x){filter(x, str_ends(`市区町村`, "村"))}))
g1 %<>% mutate(`村`=map(data, ~filter(.x, str_ends(`市区町村`, "村"))))
のように書くこともできます。
次に、村の数と面積合計を集計してみます。
g1 %<>% mutate(`村数`=map_int(`村`, nrow))
g1 %<>% mutate(`村面積合計`=map_dbl(`村`, ~sum(.x$`面積`)))
mapの中の関数をどう書いていいのかよく分からなくなってしまいます。その時は上に書いたように別に関数を作って確認しています。
ここではmapではなくmap_intやmap_dblとしています。mapだとリストを返し、そのままでは数値としての処理ができなくなってしまいます。(unnestを使えばできますが)数値ベクトルにしておく必要があります。
goup_nestだと表の中に全データが残っていますし、RStudioを使うとデータ構造がわかりやすく表示できますので便利です。