Announcing Built-in H3 Expressions for Geospatial Processing and Analytics - The Databricks Blogの翻訳です。
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
Databricksランタイム11.2は、Databricksと地理空間情報を処理、分析しているお客様にとってのマイルストーンリリースとなります。11.2のリリースではGA(正式提供)として、効率的な地理空間情報の処理や分析のための28個のビルトインH3エクスプレッションが含まれています。この記事では、H3とは何か、従来の地理空間データ処理に対してどの様な優位性を提供するのか、DatabricksでどのようにH3を使い始められるのかを説明します。最終的には、H3を用いることで、WKT、WKB、Lat/Lon、GeoJSONのような一般的なフォーマットから空間データをH3のセルIDに容易に変換し、効率的な方法でデータを空間的に集計、join、可視化できる様になります。
H3とは?
H3に初めて触れる人のために簡単な説明をします。
H3は同名のグローバルインデクシングシステムとライブラリとなります。もともとは、空間データパターンを可視化、探索する目的においてUberによって開発されました。グリッドシステムは、表面(この場合は地球の表面)のモザイクを形成するために長方形や三角形の様なシェイプをしようします。階層型グリッドシステムは、異なる解像度でモザイクを形成します(基本的なシェイプは異なるサイズで提供されます)。H3システムは、六角形(一部五角形)を使用する様に設計され、そして階層型システムとして異なる16の解像度を操作することができます。特定の解像度でデータをインデクシングすると、分析に使用する1つ以上のH3のセルIDが生成されます。例えば、解像度15のH3セルは約1$m^2$(異なるH3の解像度の詳細についてはこちらをご覧ください)をカバーします。
H3グローバルグリッドインデクシングシステムの詳細な説明については、こちらとこちらをご覧ください。
H3は広く使用されています
H3は広範な利用パターンに適用でき、高度にスケーラブルなので、さまざまな業界における地理空間データ処理で活用されています。驚くべきことではありませんが、Uberによって構築されたシステムは自動運転システムや膨大な量の空間・時間データを生成するあらゆるIoTデバイスで活用されています。また、H3は一ベースのデータプロダクトで広く使用されており、移動手段に基づく洞察を明らかにすることで、リテールの計画や交通、デリバリー、農業、テレコム、保健のオペレーションをサポートしています。これはH3がどの様に活用されているのかの一部に過ぎません。
なぜH3を使うのか?
H3システムを用いることで、膨大な量のデータを理解できる様になります。例えば、大規模なNYCのタクシー乗降データセットを用いることで、空間的なパターンをより理解するためにデータを空間的に集計することができます。10億以上のオーバーラップするデータを見たとしても、パターンを特定することはできませんが、H3を活用することで即座にパターンが明らかになり、さらならる探索に取り組める様になります。
生データ
H3セルIDによる集計データを用いることで空間パターンを明らかにすることができます
また、H3セルIDは分断したデータセットをjoinするのに適しています。すなわち、潜在的に高コストな空間述語を用いることなしに、意味論的に空間的なjoinを実行できます。セルIDを用いたデータセットのjoinを行い、位置ドリブンな疑問に答え始めることは非常にわかりやすいものです。H3を用いて空間的な問題を解くのかをさらにデモンストレーションするために、NYCタクシーデータセットを使い続けましょう。
最初に、NYCデータセットを取り込み、乗降位置を解像度15のH3セルをtrips_h3_15として変換したものとします。同様に、LaGuardiaとNewarkの空港の領域を解像度12に変換し、それぞれの空港に対応するexplodeされたビューを持つairports_h3_cに(h3_compact関数を用いて)コンパクト化したものとします。このデータセットにおいては、コンパクト化されたH3セルの解像度は8以上であり、下でこれを活用するということに触れておきます。これで、「LaGuardia空港(LGA)で生じたタクシー乗車が最も多かった地点は?」という質問に答えられる様になります。
LaGuardia空港におけるタクシーピックアップの分析
これに答えるためにsrc_airport_trips_h3_cというビューを生成し、上のようにtrip_cntで定義される色とpassenger_sumによる高さを用いてKepler.glでレンダリングしました。乗車位置、降車位置と空港を定義するH3セルを関連づけるために、h3_toparentとh3_ischildofを使用しました。
%sql
create or replace view airport_trips_h3_c as (
select
t.passenger_count,
t.fare_amount,
src.locationid as src_locationid,
trg.locationid as trg_locationid,
src.cell as src_cell,
trg.cell as trg_cell
from
trips_h3_15 t,
airports_h3_c src,
airports_h3_c trg
where
h3_toparent(t.pickup_cell, 8) = h3_toparent(src.cell, 8)
and h3_toparent(t.dropoff_cell, 8) = h3_toparent(trg.cell, 8)
and h3_ischildof(t.pickup_cell, src.cell)
and h3_ischildof(t.dropoff_cell, trg.cell)
and src.locationid <> trg.locationid
);
そして、Kepler.glのレンダリングに使用したビューsrc_airport_trips_h3_cのこれらコンパクト化されたセルのピックアップに関係する興味の領域の属性値を合計、カウントしました。
create or replace view src_airport_trips_h3_c as (
select
src_cell as cell,
src_locationid as locationid,
format_number(count(*), 0) as trip_cnt_disp,
format_number(sum(passenger_count), 0) as passenger_sum_disp,
(
'$' || cast(format_number(sum(fare_amount), 2) as string)
) as fare_sum_disp,
count(*) as trip_cnt,
sum(passenger_count) as passenger_sum,
sum(fare_amount) as fare_sum
from
airport_trips_h3_c
group by
cell,
src_locationid
);
DatabricksにおけるH3セルIDは、big integerか文字列として格納することができます。セルIDのbig integer表現を用いた際に、H3のインデックスがされたデータへのクエリーは最も高速になります。これらの表現によって、地理空間データの格納方法をさらに最適化することができます。効率的にデータを空間的に隣接させるためにZ-orderingを行うために、Delta LakeのOPTIMIZEオペレーションを活用することができます。完全にオープンソース化されているDelta Lakeには、読み込む必要があるデータ量をインテリジェントに削減するために局所性を活用するデータスキッピングアルゴリズムが含まれています。
また、H3セルの可視化もシンプルです。最も一般的で人気のあるライブラリのいくつかは、ビルトインでH3データの可視化をサポートしています。お客様は、Kepler.gl(Mosaicでもバンドルされています)の様なライブラリがアタッチされたクラスターやノートブックや、DatabricksのODBC、JDBCドライバーを用いてCARTOのような可視化ツールのインテグレーションを活用することができます。CARTOを用いることで、データにアクセスし、クエリーを行うために直接Databricksクラスターに接続することができます。CARTOのロケーションインテリジェンスプラットフォームによって、大規模データの可視化や分析、動的な集計を可能にするH3の階層化構造を活用することができ、H3のインデックスがなされたデータセットを用いた空間データカタログも活用することができます。CARTOの活用方法に関してはこちらを参照ください。
リンクをクリックすると別タブで動画が開きます
CARTOを用いたDatabricksでのH3インデックスデータの探索
H3を使い始めてみる
以下のウォークスルーのサンプルでは、NYCタクシーデータセットとNewarkとLaGuardia空港の領域を使用します。途中では、乗車、降車、乗客数、空港間の料金に関するいくつかの質問に答えていきます。
DatabricksのH3エクスプレッションを使い始めましょう。最初に、H3エクスプレッションを使用するには、Photonアクセラレーションが有効化されたクラスターを作成する必要があります。これはシンプルであり、チェックボックスをオンにするだけです。
Photon Accelerationをオンにすると、ビルトインのH3エクスプレッションを使用できる様になります
ノートブックでH3 SQLエクスプレッションのScalaあるいはPythonバインディングを使用している場合、対応するDatabricksのSQL関数バインディングをインポートする必要があります。
ScalaのDatabricksのSQL関数バインディングをインポートするには以下を実行します。
import com.databricks.sql.functions._
PythonのDatabricksのSQL関数バインディングをインポートするには以下を実行します。
from pyspark.databricks.sql.functions import *
データは既に準備されているので、作業するために選択した解像度でデータをインデクシングします。空間的地理情報(ポリゴンやマルチポリゴン)に対しては、関数h3_polyfillash3を使用することができます。緯度経度から位置をインデクシングするには、関数h3_longlatash3を使用します。我々の例では、解像度12で位置と空港の領域をインデクシングします。
%sql
-- drop table if exists airports_h3;
create table if not exists airports_h3 as (
select
locationid,
explode(h3_polyfillash3(the_geom, 12)) as cell
from
airports
)
%sql
-- drop table if exists trips_h3;
create table if not exists trips_h3 as (
select
h3_longlatash3(pickup_longitude, pickup_latitude, 12) as pickup_cell,
h3_longlatash3(dropoff_longitude, dropoff_latitude, 12) as dropoff_cell,
passenger_count,
fare_amount
from
trips
)
H3セルIDを用いることで、移動データに関する一連の質問に答えるために、容易にh3のテーブルairportとtripsを組み合わせることができます。空港間で何回移動がありましたか?何人の乗客が運ばれましたか?どれだけの料金が発生しましたか?
%sql
select
format_number(count(*),0) as num_trips,
format_number(sum(passenger_count),0) as num_passengers,
(
'$' || cast(format_number(sum(fare_amount), 2) as string)
) as earnings
from
airport_trips_h3_c
子データセットを用いて数えきれない質問を投げかけ、探索することができます。H3を用いることで、新たな方法で地理情報データを探索できる様になります。どの空港がもっともピックアップの交通量を生み出したのでしょうか?LaGuardia (LGA)とNewark (EWR)では、LGAの方がはるかにピックアップが多く、LGAで生み出される移動がEWRと比較して割合としては99%以上を占めることになることがわかりました。
%sql
create or replace temp view
src_full_airport_trips_h3_c as (
select
cell,
zone,
borough,
trip_cnt_disp,
passenger_sum_disp,
fare_sum_disp,
airports.locationid,
trip_cnt,
passenger_sum,
fare_sum
from
src_airport_trips_h3_c
inner join airports
on src_airport_trips_h3_c.locationid = airports.locationid
)
LaGuardia (LGA)から出発する際に最も共通する目的地はどこでしょうか?エアポートから出発した2500万の降車があり、NYCエリアの260のタクシーゾーンをカバーしていることがわかりました。これらの中には、移動に含まれる解像度12の83万8千のユニークなH3セルが存在しています。しかし、集計のパワーによって、容易にゾーンごとの降車イベントの総数を計算し、最も密度が高い領域を黄色にしてKelper.glでレンダリングすることができます。
ツールチップに表示される様にLGAからJFK空港に移動するピックアップが25万存在しています
この答えに辿り着く過程で、LGAを表現するlocationid = 132
でフィルタリングされたtrips_h3テーブルとairports_h3テーブルをjoinし、LGAからのピックアップセルに限定しました。これによって、初期の25Mトリップを取得することができます。
%sql
create or replace temp view lga_dropoffs as (
select
pickup_cell,
dropoff_cell,
passenger_count,
fare_amount,
air.locationid as pickup_locationid
from
trips_h3
inner join (
select
*
from
airports_h3
where
locationid = 132
) air on trips_h3.pickup_cell = air.cell
)
ここから、lga_agg_dropoffsビューとして、ユニークな83万8千の降車H3セルに集計しました。
%sql
create or replace temp view lga_agg_dropoffs as (
select
count(*) as dropoff_cnt,
dropoff_cell
from
lga_dropoffs
group by
dropoff_cell
)
(ノートブックのパート2で説明されている)次のメインのステップは、ゾーン情報を特定するために取り込んだNYCタクシーゾーンのGeoJSONとlga_agg_dropoffsビューをjoinすることです。最後のステップは、上述のレンダリングした分析結果のために、ゾーンごとのすべてのdropoff_cntの最終的な総和を計算することでした。
%sql
create or replace temp view lga_agg_zone_dropoffs_h3 as (
select
dropoff_cnt,
dropoff_cell,
locationid,
borough,
zone
from
lga_agg_dropoffs
inner join taxi_zone_explode_h3
on lga_agg_dropoffs.dropoff_cell = taxi_zone_explode_h3.cell
)
この例では、初期データをロードし、集計結果を含む追加のカラムを持つ様々なテーブルとビューを生成するためのDatabricksの既存の強力な機能と、新たに利用できるH3 APIを用いた地理空間処理をブレンドしています。また、空間的レイヤーをレンダリングするためのKepler.glや、Apache Sparkフレームワークの拡張であり、大規模地理空間データセットを容易かつ高速の処理する能力を提供するDatabricks LabsプロジェクトであるMosaicの便利な機能の様な外部のライブラリを組み込みました。
Databricksで何が使えるのか?
H3を用いて現在Databricksで何ができるのかを詳しく見ていきましょう。数多くのカテゴリー関数をカバーする28のH3関連のエクスプレッションがあります。以下にDatabricksランタイム11.2で利用できるカテゴリーごとのエクスプレッションの完全なセットを示します。
-
Import
- h3_longlatash3
- h3_longlatash3string
- h3_polyfillash3
- h3_polyfillash3string
- h3_try_polyfillash3
- h3_try_polyfillash3string
-
Export
- h3_boundaryasgeojson
- h3_boundaryaswkb
- h3_boundaryaswkt
- h3_centerasgeojson
- h3_centeraswkb
- h3_centeraswkt
-
Conversions
- h3_h3tostring
- h3_stringtoh3
-
Predicates
- h3_ischildof
- h3_ispentagon
-
Validity
- h3_isvalid
- h3_try_validate
- h3_validate
-
Distance related
- h3_distance
- h3_hexring
- h3_kring
- h3_kringdistances
-
Traversal
- h3_resolution
- h3_tochildren
- h3_toparent
-
Compaction
- h3_compact
- h3_uncompact
セルIDにはbig integerと文字列表現の両方を使用することができ、H3ライブラリで使用される表現と同じものとなります。なので、既にデータをH3でインデクシングしているのであれば、既存のセルIDを使い続けることができます。H3のセルIDにはbig integer表現を使用すること、既存のH3セルが文字列データである場合にはbig integer表現に変換することを強くお勧めします。big integerと文字列表現の変換は、h3_stringtoh3やh3_h3tostringエクスプレッションを用いて行うことができます。Databricksランタイム11.2以降には、外部依存関係としてH3ライブラリv.3.7.0が含まれます。H3エクスプレッションのDatabricks実装は、多くのケースで内部のライブラリを使用しますが、排他的なものではありません。
間も無く、全てのH3 SQLエクスプレッションがDatabricks SQLでも利用できる様になります。
DatabricksにおけるH3 SQLエクスプレッションを学ぶのであれば、こちらのドキュメントとこの記事で使用した一連のノートブックを参照ください。
訳者注 ノートブックの翻訳版を説明した記事です。