空間データの操作の基本

Rによる基本的な空間データの操作について紹介します。

geo
Author

Keisuke ANDO

Published

June 3, 2023

1. はじめに

私は交通事故を対象に空間分析をおこなっています。空間分析では地図を使って、なんらかの地点群、道路、建物などを対象に分析します。空間分析に用いられるこれらのデータを空間データといいます。空間データは点や領域などの空間を表す属性と、数値や文字列などのその空間を説明する属性をあわせもつデータです。

空間分析をおこなうためのプログラミングはそれほど一般的ではありません。そのため、なにからはじめたらよいかわからないかと思います。この記事では、交通事故地点のデータを使って空間オブジェクトの基本的な操作について説明します。

2. 使用するRPackageのインストール

Rでは空間データを扱うためのRPackageが盛んに開発されています。ここでは基本的な空間データの操作のために、次のRPackageを使用します。

  • {rtatools}: 警察庁が公開する交通事故のデータをダウンロードし、データフレームとして扱うことができるRPackage
  • {jpndistrict}: 国土交通省が提供する都道府県、市区町村といった行政区域の境界データを扱えるRPackage
  • {tmap}: 空間データをGoogle Mapのようなインタラクティブな地図上に可視化する機能などを提供するRPackage
  • {tidyverse}: 拡張されたデータフレーム、データ操作、可視化などデータ分析のためのさまざまな機能を提供するRPackageのコレクション
  • {sf}: 空間データの作成や演算のためのRPackage

これらのRPackageをインストールする前に、LinuxやMacでは{rtatools}の依存ライブラリをインストールしておく必要があります。例えば、Ubuntuでは、次のようにして事前にライブラリをインストールします。

apt-get update
apt-get install -y libpoppler-cpp-dev libudunits2-dev libproj-dev libgdal-dev

依存ライブラリをインストールしたら、Rで以下のコードを実行してRPackageをインストールします。

# CRANからのインストール
install.packages("tmap")
install.packages("tidyverse")
install.packages("sf")

# GitHubからのインストール
install.packages("devtools")
devtools::install_github("NONONOexe/rtatools", upgrade = "always")
devtools::install_github("uribo/jpndistrict", upgrade = "always")

Rでは標準パッケージリポジトリであるCRANに登録されているものはinstall.packages()でインストールすることができます。また、GitHubで公開されているものは{devtools}というRPackageのinstall_github()によりインストールすることができます。そのため、ここでは{devtools}もインストールしています。

3. データの可視化

交通事故地点のデータの取得

交通事故のデータは交通事故そのもののデータと当事者のデータの2つからなります。ここでは交通事故地点を含む交通事故そのもののデータのみ使います。このデータは次のコードを実行して取得できます。

library(rtatools)

# データのダウンロードと読み込み
data <-
  download_traffic_accidents_main() |>
  read_traffic_accidents_main()

# 交通事故のデータ
accidents <- data$traffic_accidents

# 一覧形式で表示
accidents

交通事故のデータ(一部)

recording_year prefecture police_office accident_id occurence_time day_of_week holiday day_night_type city road track kilopost region_type zone_regulation road_verge center_divider weather road_surface road_shape road_alignment carriageway_width traffic_signal roundabout_diameter injury_pattern fatalities injuries impact_type collision_position geometry
2021 10 059 0001 2020-12-28 20:25:00 2 3 22 224 40020 2 0000 3 70 4 1 2 1 12 9 04 7 00 2 0 1 21 01 c(141.619122777778, 42.8158677777778)
2021 10 059 0002 2020-12-26 14:30:00 7 3 12 222 40040 2 0000 3 70 4 1 5 4 14 9 04 7 00 2 0 2 21 01 c(141.830353888889, 43.2287838888889)
2021 10 059 0003 2020-12-02 16:55:00 4 3 21 222 40030 1 0000 3 70 4 1 2 4 14 9 04 7 00 2 0 4 21 01 c(141.830324444444, 43.2440230555556)
2021 10 059 0004 2020-12-07 07:10:00 2 3 11 213 50020 2 0000 3 70 4 1 3 3 14 9 04 7 00 2 0 1 21 01 c(141.794236666667, 42.669235)
2021 10 101 0001 2020-12-26 18:40:00 7 3 22 101 39990 0 0000 1 70 2 5 1 3 14 9 04 7 00 2 0 1 01 01 c(141.351606111111, 43.0556763888889)
2021 10 101 0002 2020-12-17 02:39:00 5 3 22 101 00360 0 0006 1 70 2 1 2 3 01 9 19 1 00 2 0 1 01 30 c(141.352983055556, 43.0565608333333)

交通事故地点の地図への描画

交通事故のデータはgeometryという項目にその地点の緯度、経度を持っています。しかし、数値ではどこで発生した事故であるのかがよくわかりません。

{tmap}を使うと空間データを地図に描画することができます。いろいろな描画の形式がありますが、ここでは、マーカーを使って描画します。

library(tmap)
Breaking News: tmap 3.x is retiring. Please test v4, e.g. with
remotes::install_github('r-tmap/tmap')
# データ数が多いため、交通事故地点の先頭100件を抽出
accidents_head_100 <- head(accidents, 100)

# インタラクティブな地図へ描画するモードへの切り替え
tmap_mode("view")
tmap mode set to interactive viewing
# 地図上に描画
tm_shape(accidents_head_100) + tm_markers()

このように交通事故地点を地図上に描画することができます。tm_markers()は指定した空間データの位置をマーカーを使って表示します。また、近くに位置するマーカーはまとめて表示します。

4. データの抽出

属性値にもとづく条件抽出

空間分析では、通常のデータ分析と同様に期間ごとにデータを分ける、ある特定の種類のデータについて抽出する、などして特定の条件に該当するデータに絞って分析することがあります。

このように条件に基づいてデータを抽出する場合、{tidyverse}のもつRPackageのひとつである{dplyr}filter()を使うと次のように簡単に抽出できます。

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
accidents_aichi_morning_rain <-
  accidents |>
  # 愛知県の交通事故を抽出(都道府県コード: 54)
  filter(prefecture == "54") |>
  # 朝6時から朝8時の間の交通事故を抽出
  filter(between(hour(occurence_time), 6, 8)) |>
  # 雨天時の事故を抽出(天候コード: 3)
  filter(weather == "3")

# 地図上に描画
tm_shape(accidents_aichi_morning_rain) + tm_markers()

ここでは全国のデータから段階的に都道府県、時間、天候の3つの条件で抽出しています。filter()は第1引数がデータで第2引数が条件であるため、データを|>(native pipe)で渡してつなげることができます。

領域にもとづく抽出

空間分析では「ある領域内に含まれるデータ」や「ある点に最も距離の近いデータ」のようにデータがもつ空間に応じた抽出もできます。空間データの処理では{sf}を使います。例えば、瀬戸市の交通事故を抽出する場合は次のようにできます。

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 <https://www.gsi.go.jp>)
library(sf)
Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
# 瀬戸市の領域を取得
seto <- jpn_cities(jis_code = "23", admin_name = "瀬戸市")
# accidents_aichi_morning_rainのうち、瀬戸市内の交通事故地点のみを抽出
accidents_seto_morning_rain <-
  accidents_aichi_morning_rain |> st_filter(seto)

# 瀬戸市の領域のレイヤー
tm_seto <- tm_shape(seto) + tm_polygons(
  alpha = 0.2, col = "yellow", border.col = "yellow")
# 交通事故地点のレイヤー
tm_accidents <- tm_shape(accidents_seto_morning_rain) + tm_markers()
# 重ね合わせて描画
tm_seto + tm_accidents

この例では、瀬戸市の領域と抽出した交通事故地点を重ね合わせて描画しています。{tmap}で描画したオブジェクトは+演算子で簡単にレイヤーとして重ね合わせることができます。またそれぞれのレイヤーやベースとなっているタイルマップの操作は左上のコントロールから操作できます。

5. まとめ

ここでは、RPackageで提供されている空間データを使って、データの可視化と抽出をおこないました。ここで紹介したもの以外にもRでは多くの空間データや操作が提供されています。なにができるかについては{sf}のドキュメントが詳しいです。また、以前{tmap}を使ったプロットについて書いた以下の記事や、公開された空間分析についての書籍もあります。こちらからはさまざまな事例をみられるので、参考になると思います。