Menangani data geospasial

Analisis geospasial memungkinkan Anda menganalisis data geografis di BigQuery. Data geografis juga dikenal sebagai data geospasial.

Jenis objek umum saat menangani data geospasial meliputi:

  • Geometri mewakili luas permukaan di Bumi. Objek ini sering dijelaskan menggunakan titik, garis, poligon, atau kumpulan titik, garis, dan poligon. Koleksi geometri adalah geometri yang mewakili penggabungan spasial semua bentuk dalam koleksi.
  • Fitur spasial mewakili objek spasial yang logis. Hal ini menggabungkan geometri dengan atribut tambahan yang spesifik untuk aplikasi.
  • Koleksi fitur spasial adalah sekumpulan fitur spasial.

Di BigQuery, jenis data GEOGRAPHY mewakili nilai geometri atau kumpulan geometri. Untuk merepresentasikan fitur spasial, buat tabel dengan kolom GEOGRAPHY untuk geometri beserta kolom tambahan untuk atribut. Setiap baris tabel adalah fitur spasial, dan seluruh tabel mewakili koleksi fitur spasial.

Jenis data GEOGRAPHY menjelaskan kumpulan titik di permukaan Bumi. Kumpulan titik adalah kumpulan titik, garis, dan poligon pada sferoid referensi WGS84, dengan tepi geodesi. Anda dapat menggunakan jenis data GEOGRAPHY dengan memanggil salah satu fungsi geografis GoogleSQL.

Memuat data geospasial

Titik tunggal di Bumi dapat digambarkan hanya dengan pasangan bujur dan lintang. Misalnya, Anda dapat memuat file CSV yang berisi nilai bujur dan lintang, lalu menggunakan fungsi ST_GEOGPOINT untuk mengonversinya menjadi nilai GEOGRAPHY.

Untuk geografi yang lebih kompleks, Anda dapat memuat format data geospasial berikut ke dalam kolom GEOGRAPHY:

  • Well-known text (WKT)
  • Well-known binary (WKB)
  • GeoJSON

Memuat data WKT atau WKB

WKT adalah format teks untuk mendeskripsikan setiap bentuk geometri menggunakan titik, garis, poligon dengan lubang opsional, atau kumpulan titik, garis, atau poligon. WKB adalah versi biner dari format WKT. WKB dapat dienkode dengan hex untuk format yang tidak mendukung data biner, seperti JSON.

Misalnya, kode berikut menentukan titik di WKT:

POINT(-121 41)

Untuk mendeskripsikan fitur spasial, WKT biasanya disematkan dalam format file container, seperti file CSV, atau dalam tabel database. Baris file atau baris tabel biasanya sesuai dengan fitur spasial. Seluruh file atau seluruh tabel sesuai dengan koleksi fitur. Untuk memuat data WKT ke BigQuery, berikan skema yang menentukan kolom GEOGRAPHY untuk data geospasial.

Misalnya, Anda mungkin memiliki file CSV yang berisi data berikut:

"POLYGON((-124.49 47.35,-124.49 40.73,-116.49 40.73,-116.49 47.35,-124.49 47.35))",poly1
"POLYGON((-85.6 31.66,-85.6 24.29,-78.22 24.29,-78.22 31.66,-85.6 31.66))",poly2
"POINT(1 2)",point1

Anda dapat memuat file ini dengan menjalankan perintah load alat command line bq:

bq load --source_format=CSV \
  --schema="geography:GEOGRAPHY,name:STRING" \
  mydataset.mytable filename1.csv

Untuk informasi selengkapnya tentang pemuatan data di BigQuery, lihat Pengantar pemuatan data.

Untuk melakukan streaming data WKT ke tabel BigQuery yang sudah ada dengan kolom GEOGRAPHY, lakukan serialisasi data sebagai string dalam permintaan API.

bq

Jalankan perintah insert alat command line bq:

echo '{"geo": "LINESTRING (-118.4085 33.9416, -73.7781 40.6413)"}' \
    | bq insert my_dataset.geo_table

Python

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Python di Panduan memulai BigQuery menggunakan library klien. Untuk mengetahui informasi selengkapnya, lihat Dokumentasi referensi BigQuery Python API.

Untuk melakukan autentikasi ke BigQuery, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, lihat Menyiapkan autentikasi untuk library klien.

from google.cloud import bigquery
import shapely.geometry
import shapely.wkt

bigquery_client = bigquery.Client()

# This example uses a table containing a column named "geo" with the
# GEOGRAPHY data type.
table_id = "my-project.my_dataset.my_table"

# Use the Shapely library to generate WKT of a line from LAX to
# JFK airports. Alternatively, you may define WKT data directly.
my_geography = shapely.geometry.LineString(
    [(-118.4085, 33.9416), (-73.7781, 40.6413)]
)
rows = [
    # Convert data into a WKT string.
    {"geo": shapely.wkt.dumps(my_geography)},
]

#  table already exists and has a column
# named "geo" with data type GEOGRAPHY.
errors = bigquery_client.insert_rows_json(table_id, rows)
if errors:
    raise RuntimeError(f"row insert failed: {errors}")
else:
    print(f"wrote 1 row to {table_id}")

Untuk informasi selengkapnya tentang streaming data di BigQuery, baca Streaming data ke BigQuery.

Anda juga dapat mengonversi string teks WKT menjadi nilai GEOGRAPHY menggunakan fungsi ST_GeogFromText.

Memuat data GeoJSON

GeoJSON adalah format berbasis JSON untuk fitur geometri dan spasial. Misalnya, kode berikut menentukan titik di GeoJSON:

{ "type": "Point", "coordinates": [-121,41] }

Data GeoJSON dapat berisi salah satu jenis objek berikut:

  • Objek geometri. Objek geometri adalah bentuk spasial, yang digambarkan sebagai gabungan titik, garis, dan poligon dengan lubang opsional.
  • Objek fitur. Objek fitur berisi geometri beserta pasangan nama/nilai tambahan, yang memiliki arti khusus untuk aplikasi.
  • Koleksi fitur. Koleksi fitur adalah sekumpulan objek fitur.

Ada dua cara untuk memuat data GeoJSON ke BigQuery:

Memuat file GeoJSON yang dibatasi newline

File GeoJSON yang dibatasi newline berisi daftar objek fitur GeoJSON, satu per baris dalam file. Objek fitur GeoJSON adalah objek JSON dengan anggota berikut:

  • type. Untuk objek fitur, nilainya harus Feature. BigQuery memvalidasi nilai, tetapi tidak menyertakannya dalam skema tabel.

  • geometry. Nilainya adalah objek Geometry GeoJSON atau null. BigQuery mengonversi anggota ini menjadi nilai GEOGRAPHY.

  • properties. Nilainya berupa objek JSON atau null. Jika nilainya bukan null, BigQuery akan memuat setiap anggota objek JSON sebagai kolom tabel terpisah. Untuk informasi selengkapnya tentang cara BigQuery mengurai jenis data JSON, lihat Detail pemuatan data JSON.

  • id. Opsional. Jika ada, nilainya bisa berupa string atau angka. BigQuery memuat nilai ini ke dalam kolom bernama id.

Jika objek fitur berisi anggota lain yang tidak tercantum di sini, BigQuery akan mengonversi anggota tersebut langsung ke dalam kolom tabel.

Anda dapat memuat file GeoJSON yang dibatasi newline menggunakan perintah bq load alat command line bq, seperti berikut:

bq load \
 --source_format=NEWLINE_DELIMITED_JSON \
 --json_extension=GEOJSON \
 --autodetect \
 DATASET.TABLE \
 FILE_PATH_OR_URI

Ganti kode berikut:

  • DATASET adalah nama set data Anda.
  • TABLE adalah nama tabel tujuan.
  • FILE_PATH_OR_URI adalah jalur ke file lokal atau Cloud Storage URI.

Contoh sebelumnya mengaktifkan deteksi otomatis skema. Untuk memiliki lebih banyak kontrol atas cara BigQuery mengonversi nilai di dalam objek properties, Anda dapat memberikan skema eksplisit. Untuk mengetahui informasi selengkapnya, lihat Menentukan skema. Jika Anda memberikan skema eksplisit, jangan sertakan kolom type tingkat atas dalam definisi skema. Untuk setiap anggota properties, tentukan kolom terpisah, bukan kolom bertingkat.

Seperti yang didefinisikan oleh RFC 7946, struktur data GeoJSON yang lengkap adalah objek JSON tunggal. Banyak sistem mengekspor data GeoJSON sebagai satu objek FeatureCollection yang berisi semua geometri. Untuk memuat format ini ke BigQuery, Anda harus mengonversi file tersebut dengan menghapus objek FeatureCollection tingkat root dan membagi objek fitur individual menjadi baris yang terpisah. Misalnya, perintah berikut menggunakan alat command line jq untuk membagi file GeoJSON ke dalam format yang dibatasi newline:

cat ~/file1.json | jq -c '.features[]' > converted.json

Membuat tabel eksternal dari file GeoJSON yang dibatasi newline

Anda dapat membuat kueri file GeoJSON yang dibatasi newline yang disimpan di Cloud Storage dengan membuat tabel eksternal. Untuk membuat tabel eksternal, gunakan pernyataan CREATE EXTERNAL TABLE DDL. Dalam klausa OPTIONS, tetapkan opsi format ke NEWLINE_DELIMITED_JSON dan opsi json_extension ke GEOJSON.

Contoh:

CREATE EXTERNAL TABLE mydataset.table1 OPTIONS (
  format="NEWLINE_DELIMITED_JSON",
  json_extension = 'GEOJSON',
  uris = ['gs://mybucket/geofile.json']
);

Memuat data geometri GeoJSON

Analisis geospasial mendukung pemuatan objek geometri GeoJSON individual yang disematkan sebagai string teks dalam jenis file lain. Misalnya, Anda dapat memuat file CSV yang salah satu kolomnya berisi objek geometri GeoJSON.

Untuk memuat jenis data GeoJSON ini ke BigQuery, berikan skema yang menentukan kolom GEOGRAPHY untuk data GeoJSON. Anda harus memberikan skema secara manual. Atau, jika deteksi otomatis diaktifkan, BigQuery akan memuat data sebagai nilai STRING.

Analisis geospasial tidak mendukung pemuatan objek fitur GeoJSON atau koleksi fitur menggunakan pendekatan ini. Jika Anda perlu memuat objek fitur, sebaiknya gunakan file GeoJSON yang dibatasi newline.

Untuk melakukan streaming data GeoJSON ke tabel BigQuery yang sudah ada dengan kolom GEOGRAPHY, lakukan serialisasi data sebagai string dalam permintaan API.

bq

Jalankan perintah insert alat command line bq:

echo '{"geo": "{\"type\": \"LineString\", \"coordinates\": [[-118.4085, 33.9416], [-73.7781, 40.6413]]}"}' \
  | bq insert my_dataset.geo_table

Python

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Python di Panduan memulai BigQuery menggunakan library klien. Untuk mengetahui informasi selengkapnya, lihat Dokumentasi referensi BigQuery Python API.

Untuk melakukan autentikasi ke BigQuery, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, lihat Menyiapkan autentikasi untuk library klien.

import geojson
from google.cloud import bigquery

bigquery_client = bigquery.Client()

# This example uses a table containing a column named "geo" with the
# GEOGRAPHY data type.
table_id = "my-project.my_dataset.my_table"

# Use the python-geojson library to generate GeoJSON of a line from LAX to
# JFK airports. Alternatively, you may define GeoJSON data directly, but it
# must be converted to a string before loading it into BigQuery.
my_geography = geojson.LineString([(-118.4085, 33.9416), (-73.7781, 40.6413)])
rows = [
    # Convert GeoJSON data into a string.
    {"geo": geojson.dumps(my_geography)}
]

#  table already exists and has a column
# named "geo" with data type GEOGRAPHY.
errors = bigquery_client.insert_rows_json(table_id, rows)
if errors:
    raise RuntimeError(f"row insert failed: {errors}")
else:
    print(f"wrote 1 row to {table_id}")

Anda juga dapat mengonversi objek geometri GeoJSON menjadi nilai GEOGRAPHY menggunakan fungsi ST_GEOGFROMGEOJSON. Misalnya, Anda dapat menyimpan geometri sebagai nilai STRING, lalu menjalankan kueri yang memanggil ST_GEOGFROMGEOJSON.

Sistem koordinat dan tepi

Dalam analisis geospasial, titik adalah posisi pada permukaan sferoid WGS84, yang dinyatakan sebagai bujur dan lintang geodesi. Tepi adalah geodesi sferoid di antara dua titik akhir. (Artinya, tepi adalah jalur terpendek pada permukaan bola dunia.)

Format WKT tidak menyediakan sistem koordinat. Saat memuat data WKT, analisis geospasial mengasumsikan data tersebut menggunakan koordinat WGS84 dengan tepi sferoid. Pastikan data sumber Anda cocok dengan sistem koordinat tersebut, kecuali jika geografis cukup kecil sehingga perbedaan antara tepi sferoid dan planar dapat diabaikan.

GeoJSON secara eksplisit menggunakan koordinat WGS84 dengan tepi planar. Saat memuat data GeoJSON, analisis geospasial mengubah tepi planar menjadi tepi sferoid. Analisis geospasial menambahkan titik lain ke garis sesuai kebutuhan, sehingga urutan tepi yang dikonversi tetap berada dalam jarak 10 meter dari garis asli. Proses ini dikenal sebagai teselasi atau densifikasi tidak seragam. Anda tidak dapat mengontrol proses teselasi secara langsung.

Untuk memuat area geografis dengan tepi sferoid, gunakan WKT. Untuk memuat geografi dengan tepi planar, yang sering disebut geometri, cara yang paling sederhana adalah menggunakan GeoJSON. Namun, jika data geometri Anda sudah dalam format WKT, opsi lainnya adalah memuat data sebagai jenis STRING, lalu menggunakan ST_GEOGFROMTEXT fungsi untuk mengonversi ke nilai GEOGRAPHY. Tetapkan parameter planar ke TRUE untuk menafsirkan data sebagai planar.

Saat memilih format pertukaran, pastikan untuk memahami sistem koordinat yang digunakan oleh data sumber Anda. Sebagian besar sistem secara eksplisit mendukung penguraian geografi (bukan geometri) dari WKT, atau sistem akan menggunakan tepi planar.

Koordinat Anda harus berupa bujur pertama, lintang kedua. Jika geografi memiliki segmen atau tepi yang panjang, segmen atau tepi tersebut harus di-teselasi, karena analisis geospasial menafsirkannya sebagai geodesi sferoid, yang mungkin tidak sesuai dengan sistem koordinat tempat data Anda berasal.

Orientasi poligon

Pada bola dunia, setiap poligon memiliki poligon komplementer. Misalnya, poligon yang menggambarkan benua Bumi akan memiliki poligon komplementer yang menggambarkan samudra Bumi. Karena kedua poligon dijelaskan oleh lingkaran batas yang sama, aturan diperlukan untuk mengatasi ambiguitas terkait manakah dari dua poligon tersebut yang dijelaskan oleh string WKT tertentu.

Saat Anda memuat string WKT dan WKB dari file atau dengan menggunakan penyerapan streaming, analisis geospasial mengasumsikan poligon dalam input berorientasi sebagai berikut: Jika Anda melintasi batas poligon dalam urutan verteks input, bagian dalam poligon berada di sebelah kiri. Analisis geospasial menggunakan aturan yang sama saat mengekspor objek geografi ke string WKT dan WKB.

Jika Anda menggunakan fungsi ST_GeogFromText untuk mengonversi string WKT menjadi nilai GEOGRAPHY, parameter oriented akan menentukan cara fungsi menentukan poligon:

  • FALSE: Menafsirkan input sebagai poligon dengan area yang lebih kecil. Ini adalah perilaku default.

  • TRUE: Gunakan aturan orientasi kiri yang dijelaskan sebelumnya. Opsi ini memungkinkan Anda memuat poligon dengan area yang lebih besar dari belahan bumi.

Karena string GeoJSON ditentukan pada peta planar, orientasi dapat ditentukan tanpa ambiguitas, meskipun input tersebut tidak mengikuti aturan orientasi yang ditentukan dalam spesifikasi format GeoJSON, RFC 7946.

Menangani data spasial yang tidak diformat dengan benar

Saat memuat data spasial dari alat lain ke BigQuery, Anda mungkin mengalami error konversi karena data WKT atau GeoJSON yang tidak valid. Misalnya, error seperti Edge K has duplicate vertex with edge N menunjukkan bahwa poligon memiliki verteks duplikat (selain verteks yang pertama dan terakhir).

Untuk menghindari masalah pemformatan, Anda dapat menggunakan fungsi yang menghasilkan output yang sesuai dengan standar. Misalnya, saat mengekspor data dari PostGIS, Anda dapat menggunakan fungsi ST_MakeValid PostGIS untuk menstandarkan output. Atau, impor data sebagai teks, lalu konversikan dengan memanggil ST_GEOGFROMTEXT atau ST_GEOGFROMGEOJSON dengan parameter make_valid. Jika make_valid adalah TRUE, fungsi ini akan mencoba memperbaiki poligon yang tidak valid.

Untuk menemukan atau mengabaikan data yang diformat dengan tidak benar, gunakan awalan fungsi SAFE untuk membuat output data yang bermasalah. Misalnya, kueri berikut menggunakan awalan SAFE untuk mengambil data spasial yang tidak diformat dengan benar.

SELECT
  geojson AS bad_geojson
FROM
  mytable
WHERE
  geojson IS NOT NULL
  AND SAFE.ST_GeogFromGeoJson(geojson) IS NULL

Batasan

Analisis geospasial tidak mendukung fitur berikut dalam format geospasial:

  • Geometri tiga dimensi. Geometri ini mencakup akhiran "Z" dalam format WKT, dan koordinat ketinggian dalam format GeoJSON.
  • Sistem referensi linear. Opsi ini mencakup akhiran "M" dalam format WKT.
  • Objek geometri WKT selain primitif geometri atau geometri multibagian. Secara khusus, analisis geospasial hanya mendukung Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, dan GeometryCollection.

Lihat ST_GeogFromGeoJson dan ST_GeogFromText untuk batasan khusus format input GeoJson dan WKT.

Memuat data geospasial Google Earth Engine

Google Earth Engine adalah platform data geospasial yang mengumpulkan dan menganalisis insight dari citra pengamatan satelit dan bumi menggunakan data raster, yang mana data diatur dalam petak sel yang mewakili informasi pada gambar digital. Meskipun BigQuery terutama berfungsi dengan data vektor tabulasi, pengguna dapat menggunakan data BigQuery bersama dengan data raster dari Earth Engine untuk menggabungkan set data vektor dan raster dalam alur kerja mereka.

Untuk informasi tentang cara mengekspor data Earth Engine ke BigQuery, lihat Mengekspor ke BigQuery.

Mentransformasi data geospasial

Jika tabel Anda berisi kolom terpisah untuk garis bujur dan lintang, Anda dapat mengubah nilai menjadi geografi dengan menggunakan fungsi geografi GoogleSQL seperti ST_GeogPoint. Misalnya, jika memiliki dua kolom DOUBLE untuk bujur dan lintang, Anda dapat membuat kolom geografi dengan kueri berikut:

SELECT
  *,
  ST_GeogPoint(longitude, latitude) AS g
FROM
  mytable

BigQuery dapat mengonversi string WKT dan GeoJSON menjadi jenis geografi. Jika data Anda dalam format lain seperti Shapefile, gunakan alat eksternal untuk mengonversi data ke format file input yang didukung, seperti file CSV, dengan kolom GEOGRAPHY yang dienkode sebagai string WKT atau GeoJSON.

Mempartisi dan mengelompokkan data geospasial

Anda dapat mempartisi dan mengelompokkan tabel yang berisi kolom GEOGRAPHY. Anda dapat menggunakan kolom GEOGRAPHY sebagai kolom pengelompokan, tetapi tidak dapat menggunakan kolom GEOGRAPHY sebagai kolom partisi.

Jika Anda menyimpan data GEOGRAPHY dalam tabel dan kueri memfilter data menggunakan predikat spasial, pastikan tabel tersebut dikelompokkan menurut kolom GEOGRAPHY. Tindakan ini biasanya dapat meningkatkan performa kueri dan dapat mengurangi biaya. Predikat spasial memanggil fungsi geografi boolean dan memiliki kolom GEOGRAPHY sebagai salah satu argumen. Contoh berikut menunjukkan predikat spasial yang menggunakan fungsi ST_DWithin:

WHERE ST_DWithin(geo, ST_GeogPoint(longitude, latitude), 100)

Menggunakan JOIN dengan data spasial

JOIN spasial adalah gabungan dari dua tabel dengan fungsi geografis predikat dalam klausa WHERE. Contoh:

-- how many stations within 1 mile range of each zip code?
SELECT
    zip_code AS zip,
    ANY_VALUE(zip_code_geom) AS polygon,
    COUNT(*) AS bike_stations
FROM
    `bigquery-public-data.new_york.citibike_stations` AS bike_stations,
    `bigquery-public-data.geo_us_boundaries.zip_codes` AS zip_codes
WHERE ST_DWithin(
         zip_codes.zip_code_geom,
         ST_GeogPoint(bike_stations.longitude, bike_stations.latitude),
         1609.34)
GROUP BY zip
ORDER BY bike_stations DESC

Gabungan spasial berperforma lebih baik jika data geografi Anda dipertahankan. Contoh di atas membuat nilai geografi dalam kueri. Menyimpan nilai geografi dalam tabel BigQuery akan lebih efektif.

Misalnya, kueri berikut mengambil pasangan bujur dan lintang, lalu mengonversinya menjadi titik geografis. Saat menjalankan kueri ini, Anda menentukan tabel tujuan baru untuk menyimpan hasil kueri:

SELECT
  *,
  ST_GeogPoint(pLongitude, pLatitude) AS p
FROM
  mytable

BigQuery menerapkan JOIN spasial yang dioptimalkan untuk operator INNER JOIN dan CROSS JOIN dengan fungsi predikat GoogleSQL berikut:

Gabungan spasial tidak dioptimalkan:

  • Untuk gabungan LEFT, RIGHT, atau FULL OUTER
  • Dalam kasus yang melibatkan gabungan ANTI
  • Jika predikat spasial ditiadakan

JOIN yang menggunakan predikat ST_DWithin hanya dioptimalkan jika parameter jarak merupakan ekspresi konstanta.

Mengekspor data spasial

Saat Anda mengekspor data spasial dari BigQuery, nilai kolom GEOGRAPHY selalu diformat sebagai string WKT. Untuk mengekspor data dalam format GeoJSON, gunakan fungsi ST_AsGeoJSON.

Jika alat yang digunakan untuk menganalisis data yang diekspor tidak memahami jenis data GEOGRAPHY, Anda dapat mengonversi nilai kolom menjadi string menggunakan fungsi geografis seperti ST_AsText atau ST_AsGeoJSON. Analisis geospasial menambahkan titik tambahan ke garis jika diperlukan sehingga urutan tepi yang dikonversi tetap berada dalam jarak 10 meter dari garis geodesi asli.

Misalnya, kueri berikut menggunakan ST_AsGeoJSON untuk mengonversi nilai GeoJSON menjadi string.

SELECT
  ST_AsGeoJSON(ST_MakeLine(ST_GeogPoint(1,1), ST_GeogPoint(3,2)))

Data yang dihasilkan akan terlihat seperti berikut:

{ "type": "LineString", "coordinates": [ [1, 1], [1.99977145571783, 1.50022838764041], [2.49981908082299, 1.75018082434274], [3, 2] ] }

Garis GeoJSON memiliki dua titik tambahan. Analisis geospasial menambahkan titik-titik ini sehingga garis GeoJSON mengikuti jalur yang sama pada bumi dengan garis aslinya.

Langkah selanjutnya