本文へスキップ
からだにいいもの

Rのトピックスを中心に『まだ、まだ、知らない、役に立つ情報?』を発信します。

Rで解析:GeoArrowで大規模なDeck.glレイヤーを地図に追加する「deckglgeoarrow」パッケージの紹介

地理空間情報を可視化する作業では、大量のデータを効率的に処理し、正確に表現することが求められます。特に、地図上でのデータレイヤー管理は複雑になりがちです。本パッケージは高性能なGeoArrowメモリーレイアウトを活用してdeck.glのレイヤーを描画することで、地図上にScatterplot、Path、Polygonの各種レイヤーを簡単に追加できるだけでなく、非常に大きなデータレイヤーも高品質に可視化することが可能です。

また、WKやsfなどのRパッケージでサポートされているデータクラスにも対応しているほか、データの値を色や線幅などにマッピングするアクセッサーや、スタイリング、ツールチップ、ポップアップ機能のコマンドも収録されています。

作成した地図はインタラクティブな操作が可能です。

パッケージバージョンは0.0.2。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。

パッケージのインストール

下記コマンドを実行してください。

# パッケージのインストール
install.packages("deckglgeoarrow")
# パッケージの読み込み
library("deckglgeoarrow")

# コマンド例実行で必要なパッケージを読み込み
# install.packages("wk")
library("wk")
# install.packages("mapgl")
library("mapgl")
スポンサーリンク

コマンド例

レイヤーの塗り色・線幅などを設定:dataAccessorsコマンド

deck.glのレイヤーは、点の半径や色、線の太さといった見た目の設定を「データアクセッサー」と呼ばれる仕組みで管理しています。dataAccessors()は、このパッケージが使うレイヤーすべての初期設定(getRadius = 1、getColor = 黒、getFillColor = 半透明の黒、getLineWidth = 1など)をまとめて持っており、変更したい項目だけを引数で指定すると、その部分だけが上書きされます。色を指定するgetColorやgetFillColorなどは、c(0, 0, 255, 130)のようなrgba(赤・緑・青・透明度)の数値ベクトルでも、”#ff00ffaa”のような16進数のカラーコードでも指定できます。

# 選択したアクセッサーを変更
dataAccessors(
  getFillColor = c(0, 0, 255, 130),
  getLineColor = "#ff00ffaa"
)

実行結果:

$getRadius
[1] 1

$getColor
[1]   0   0   0 255

$getFillColor
[1]   0   0   0 130

$getLineColor
[1]   0   0   0 255

$getLineWidth
[1] 1

$getElevation
[1] 1000

$getWidth
[1] 1
…(以下略)

deck.gl内部で使われるレイヤーIDを生成:generateDeckglLayerIdコマンド

Deck.glは、interleaved = TRUE(各レイヤー関数の初期値)の場合、maplibreのcanvasにレイヤーを挿入します。その際、指定したlayer_idから内部的な専用のレイヤーIDが生成されます。この関数を使うと、R側でその内部IDを事前に生成し、mapgl::add_layers_control()など他のコントロールでの利用が可能です。

オプション意味初期値
layer_id対象のaddGeoArrowDeckgl*レイヤー関数に渡したlayer_idを指定
beforeId対象のレイヤー関数に渡したbeforeIdを指定NULL
# "my_scatterplot_layer" というIDのDeck.glレイヤーIDを生成する
generateDeckglLayerId("my_scatterplot_layer")
# "water" を前のIDとしてDeck.glレイヤーIDを生成する
generateDeckglLayerId(beforeId = "water")

実行結果:

[1] "deck-layer-group-slot:my_scatterplot_layer"
[1] "deck-layer-group-before:water"

同梱される外部JSライブラリのバージョンを確認:extJSLibsコマンド

# 外部のJSライブラリのバージョンを確認
extJSLibs()

実行結果:

deck.gl-geoarrow          deck.gl
         "0.3.1"          "9.3.2"

ポップアップとツールチップの表示設定:popupOptions・tooltipOptionsコマンド

popupOptions()とtooltipOptions()は、maplibregl PopupOptionsに渡すオプションを指定する関数で、既定値のみが異なります。popupOptionsの既定値はanchor=”bottom”、className=”deckglgeoarrow-popup”など、tooltipOptionsの既定値はanchor=”top-left”、className=”deckglgeoarrow-tooltip”などです。

# ポップアップのデフォルトオプションを表示
popupOptions()
# ツールチップのデフォルトオプションを表示
tooltipOptions()

# ツールチップのアンカー位置とクラス名を変更
tooltipOptions(anchor = "bottom-right", className = "my-css-class-name")

実行結果(popupOptions()):

$anchor
[1] "bottom"

$className
[1] "deckglgeoarrow-popup"

$closeButton
[1] TRUE

$closeOnClick
[1] FALSE

$closeOnMove
[1] FALSE

$focusAfterOpen
[1] TRUE

$maxWidth
[1] "none"

$offset
[1] 0

$subpixelPositioning
[1] FALSE

地図にPath(線)レイヤーを追加:addGeoArrowPathLayerコマンド

オプション意味初期値
mapレイヤーを追加する対象のmaplibre()またはmapboxgl()地図オブジェクトを指定
dataLINESTRINGまたはMULTILINESTRING形式のsfオブジェクトを指定
fileGeoArrowまたはGeoParquetファイルのローカルパスを指定
urlリモートホストされたGeoArrowまたはGeoParquetファイルのURLを指定
layer_idレイヤーのID“path”
geom_column_nameジオメトリ列の名前“geometry”
popupポップアップを表示するか。TRUEなら全属性、指定された列名ならその列のみ、NULLやFALSEなら無表示NULL
tooltipツールチップを表示するか。TRUEなら全属性、指定された列名ならその列のみ、NULLやFALSEなら無表示NULL
render_optionsレンダリングオプションのリストrenderOptions()
data_accessorsデータアクセッサーのリストdataAccessors()
popup_optionsポップアップのオプションを指定するリストpopupOptions()
tooltip_optionsツールチップのオプションを指定するリストtooltipOptions()
# ベースマップのスタイルを指定
style_positron <- "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"

# 地図オブジェクトを作成
m <- maplibre(style = style_positron)

## 単一のwk LINESTRING
ln <- wkt("LINESTRING (30 10, 10 30, 40 40)")

# 単一のLINESTRINGからPathレイヤーを追加
m |>
  addGeoArrowPathLayer(
    data = ln
    , data_accessors = dataAccessors(
      getColor = "#ff000080"
      , getWidth = 3
    )
  )

## リモートホストのparquetファイル
## CRANチェックで警告が出ないよう、URLを分割して結合
base_url <- "https://raw.githubusercontent.com/geoarrow/"
data_url <- "geoarrow-data/v0.2.0/example/files/example_linestring_native.parquet"
url <- paste0(base_url, data_url)

# リモートのGeoParquetファイルからPathレイヤーを追加
m |>
  addGeoArrowPathLayer(
    url = url
    , geom_column_name = "geometry"
    , data_accessors = dataAccessors(
      getColor = "#0000ff90"
      , getWidth = 5
    )
    , popup = TRUE
    , tooltip = TRUE
  )

地図にPolygon(多角形)レイヤーを追加:addGeoArrowPolygonLayerコマンド

オプション意味初期値
mapレイヤーを追加する対象のmaplibre()またはmapboxgl()地図オブジェクトを指定
dataPOLYGONまたはMULTIPOLYGON形式のsfオブジェクトを指定
fileGeoArrowまたはGeoParquetファイルのローカルパスを指定
urlリモートホストされたGeoArrowまたはGeoParquetファイルのURLを指定
layer_idレイヤーのID“polygon”
geom_column_nameジオメトリ列の名前“geometry”
popupポップアップを表示するか。TRUEなら全属性、指定された列名ならその列のみ、NULLやFALSEなら無表示NULL
tooltipツールチップを表示するか。TRUEなら全属性、指定された列名ならその列のみ、NULLやFALSEなら無表示NULL
render_optionsレンダリングオプションのリストrenderOptions()
data_accessorsデータアクセッサーのリストdataAccessors()
popup_optionsポップアップのオプションを指定するリストpopupOptions()
tooltip_optionsツールチップのオプションを指定するリストtooltipOptions()
# ベースマップのスタイルを指定
style_positron <- "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"

# 地図オブジェクトを作成
m <- maplibre(style = style_positron)

## 単一のwk POLYGON
pl <- wkt("POLYGON ((30 10, 10 30, 40 40, 30 10))")

# 単一のPOLYGONからPolygonレイヤーを追加(beforeIdで既存の"water"レイヤーの下に挿入)
m |>
  addGeoArrowPolygonLayer(
    data = pl
    , render_options = renderOptions(
      beforeId = "water"
    )
  )

## リモートホストのparquetファイル
## CRANチェックで警告が出ないよう、URLを分割して結合
base_url <- "https://raw.githubusercontent.com/geoarrow/"
data_url <- "geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries_native.parquet"
url = paste0(base_url, data_url)

# リモートのGeoParquetファイルからPolygonレイヤーを追加
m |>
  addGeoArrowPolygonLayer(
    url = url
    , geom_column_name = "geometry"
    , render_options = renderOptions(
      extruded = FALSE
      , stroked = TRUE
    )
    , popup = TRUE
    , tooltip = TRUE
  )

地図にScatterplot(点)レイヤーを追加:addGeoArrowScatterplotLayerコマンド

オプション意味初期値
mapレイヤーを追加する対象のmaplibre()またはmapboxgl()地図オブジェクトを指定
dataPOINTまたはMULTIPOINT形式のsfオブジェクトを指定
fileGeoArrowまたはGeoParquetファイルのローカルパスを指定
urlリモートホストされたGeoArrowまたはGeoParquetファイルのURLを指定
layer_idレイヤーのID“scatter”
geom_column_nameジオメトリ列の名前“geometry”
popupポップアップを表示するか。TRUEなら全属性、指定された列名ならその列のみ、NULLやFALSEなら無表示NULL
tooltipツールチップを表示するか。TRUEなら全属性、指定された列名ならその列のみ、NULLやFALSEなら無表示NULL
render_optionsレンダリングオプションのリストrenderOptions()
data_accessorsデータアクセッサーのリストdataAccessors()
popup_optionsポップアップのオプションを指定するリストpopupOptions()
tooltip_optionsツールチップのオプションを指定するリストtooltipOptions()
# ベースマップのスタイルを指定
style_positron = "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"

# 地図オブジェクトを作成
m <- maplibre(style = style_positron)

## 単一のwk POINT
pt <- wkt("POINT (0 0)")

# 単一のPOINTからScatterplotレイヤーを追加
m |>
  addGeoArrowScatterplotLayer(
    data = pt, layer_id = "wk_point")

## wk POINTのデータフレーム
# 生成する点の数を指定
n = 5e3

# ランダムな緯度経度の点群を生成
pts = xy(
  x = runif(n, -180, 180), y = runif(n, -50, 50), crs = 4326)

# 点群からデータフレームを作成
dat <- data.frame(
  id = 1:length(pts), geometry = pts)

# 塗り色をランダムに割り当て
dat$fillColor <- sample(hcl.colors(n, alpha = sample(seq(0, 1, length.out = n))))
# 線の色をランダムに割り当て
dat$lineColor <- sample(
  hcl.colors(n, alpha = sample(seq(0, 1, length.out = n)), palette = "inferno"))
# 半径をランダムに割り当て
dat$radius <- sample.int(15, nrow(dat), replace = TRUE)
# 線の太さをランダムに割り当て
dat$lineWidth <- sample.int(5, nrow(dat), replace = TRUE)

# ナビゲーションコントロールと地球儀表示コントロールを追加した地図を作成
m <- maplibre(
  style = style_positron) |>
  add_navigation_control(visualize_pitch = TRUE) |>
  add_globe_control()

# データフレームの各列をアクセッサーに割り当ててScatterplotレイヤーを追加
m |>
  addGeoArrowScatterplotLayer(
    data = dat, layer_id = "wk-points-layer", geom_column_name = "geometry",
    render_options = renderOptions(), data_accessors = dataAccessors(
      getRadius = "radius", getFillColor = "fillColor",
      getLineWidth = "lineWidth", getLineColor = "lineColor"),
    popup = TRUE, popup_options = popupOptions(anchor = "bottom-right"),
    tooltip = TRUE, tooltip_options = tooltipOptions(anchor = "top-left"))

レイヤーごとの描画オプションを設定:renderOptionsコマンド

dataAccessors()と同様、deck.glの各レイヤー種別が持つ描画オプション(線の太さの単位や最小・最大ピクセル数など)の初期値をまとめて保持し、”…”引数で指定した名前のオプションだけを上書きする関数です。全レイヤー共通のオプションとしてbeforeIdとzIndexがあり、beforeIdを指定すると、そのレイヤーを既存の地図レイヤー(例えば”water”)の下に差し込んで描画できます。zIndexは、beforeId未指定時に複数レイヤーの重ね順を決めるために使用され、値が大きいほど上に描画されます。

# デフォルトの設定を表示
renderOptions()

# 選択したオプションを変更
renderOptions(radiusUnits = "meters", radiusScale = 10)

実行結果:

$radiusUnits
[1] "pixels"

$radiusScale
[1] 1

$lineWidthUnits
[1] "pixels"

$lineWidthScale
[1] 1

$stroked
[1] TRUE

$filled
[1] TRUE

$radiusMinPixels
[1] 3
…(以下略)


この記事が誰かの役に立ちますように。

スポンサーリンク
価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
当サイトに表示されている商品情報はAmazonから提供されたものであり、更新または削除される場合があります。
karada-goodはAmazonアソシエイトとして、適格販売により収入を得ています。