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

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
…(以下略)


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

スポンサーリンク
Prices and shipping availability may change. Please refer to the product page at time of purchase.
Content displayed on this site is provided by Amazon and may be updated or removed.
Amazon Associate, karada-good earns income through qualifying sales.