使用地理空間資料
地理空間分析可讓您在 BigQuery 中分析地理資料,地理資料也稱為地理空間資料。
使用地理空間資料時的常見物件類型包括以下項目:
- 幾何圖代表地球上的表面區域,通常使用點、線、多邊形或點、線與多邊形的集合描述。幾何集合是一種幾何圖形,代表集合中所有形狀的空間聯集。
- 空間特徵代表邏輯空間物件,結合了幾何圖形與應用程式專屬的其他屬性。
- 空間特徵集合是一組空間特徵。
在 BigQuery 中,GEOGRAPHY
資料類型代表幾何圖形值或幾何圖形集合。如要表示空間地圖項目,請建立資料表,其中包含用於幾何圖形的 GEOGRAPHY
資料欄,以及用於屬性的其他資料欄。表格的每一列都是空間特徵,整個表格則代表空間特徵集合。
GEOGRAPHY
資料類型描述地球表面上的點集合。點集合是 WGS84 參考橢圓體上的點、線和多邊形集合,含測地線。您可以透過呼叫其中一個 GoogleSQL 地理位置函式來使用 GEOGRAPHY
資料類型。
載入地理空間資料
地球上的單一點只需經緯度組合即可描述。舉例來說,您可以載入含有經緯度值的 CSV 檔案,然後使用 ST_GEOGPOINT
函式將這些值轉換為 GEOGRAPHY
值。
對於較複雜的地理區域,您可以將下列地理空間資料格式載入至 GEOGRAPHY
欄:
- 熟知的文字 (WKT)
- 熟知的二進位檔 (WKB)
- GeoJSON
- GeoParquet
載入 WKT 或 WKB 資料
WKT 是一種文字格式,用來描述個別的幾何形狀,通常使用點、線、含選用孔的多邊形或點、線或多邊形的集合描述。WKB 是 WKT 格式的二進位版本。對於不支援二進位資料的格式 (例如 JSON),WKB 可使用十六進位編碼。
例如,以下是 WKT 格式的點定義:
POINT(-121 41)
如要描述空間特徵,WKT 通常會嵌入某些容器檔案格式 (例如 CSV 檔案) 或資料庫資料表中。檔案資料列或資料表資料列通常會對應於空間特徵。整個檔案或整個資料表都對應至特徵集合。如要將 WKT 資料載入 BigQuery,請提供結構定義,為地理空間資料指定 GEOGRAPHY
資料欄。
舉例來說,您可能會使用包含下列資料的 CSV 檔案:
"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
您可以執行 bq 指令列工具 load
指令來載入這個檔案:
bq load --source_format=CSV \
--schema="geography:GEOGRAPHY,name:STRING" \
mydataset.mytable filename1.csv
如要進一步瞭解如何在 BigQuery 中載入資料,請參閱「載入資料簡介」。
如要將 WKT 資料以串流方式傳送至具有 GEOGRAPHY
欄的現有 BigQuery 資料表,請在 API 要求中將資料序列化為字串。
bq
執行 bq 指令列工具 insert
指令:
echo '{"geo": "LINESTRING (-118.4085 33.9416, -73.7781 40.6413)"}' \
| bq insert my_dataset.geo_table
Python
在嘗試這個範例之前,請先按照 BigQuery 快速入門:使用用戶端程式庫中的 Python 設定說明進行操作。詳情請參閱 BigQuery Python API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。詳情請參閱「設定用戶端程式庫的驗證機制」。
如要進一步瞭解 BigQuery 中的串流資料,請參閱「以串流方式將資料傳入 BigQuery」一文。
您也可以使用 ST_GeogFromText
函式,將 WKT 文字字串轉換為 GEOGRAPHY
值。
載入 GeoJSON 資料
GeoJSON 是一種以 JSON 為基礎的幾何和空間特徵格式。例如,以下是 GeoJSON 中定義點的方式:
{ "type": "Point", "coordinates": [-121,41] }
GeoJSON 資料可包含下列任一物件類型:
- 幾何圖形物件:這種空間形狀是由一組點、線及含有自選孔洞的多邊形所組成。
- 地圖項目物件:包含幾何圖形,以及額外的名稱/值組 (依個別應用程式而不同)。
- 地圖項目集合:地圖項目集合是一組地圖項目物件。
將 GeoJSON 資料載入 BigQuery 有兩種方法:
載入以換行符號分隔的 GeoJSON 檔案
以換行符號分隔的 GeoJSON 檔案包含 GeoJSON 地圖項目物件清單,每行一個。GeoJSON 地圖項目物件是 JSON 物件,其中包含下列成員:
type
。對於地圖項目物件,值必須為Feature
。BigQuery 會驗證值,但不會將其納入資料表結構定義。geometry
。值為 GeoJSONGeometry
物件或null
。BigQuery 會將這個成員轉換為GEOGRAPHY
值。properties
。值為任何 JSON 物件或空值。如果值不是null
,BigQuery 會將 JSON 物件的每個成員載入為個別的資料表欄。如要進一步瞭解 BigQuery 如何剖析 JSON 資料類型,請參閱「載入 JSON 資料的詳細資料」。id
。選填。如果提供,則值為字串或數字。BigQuery 會將這個值載入名為id
的資料欄。
如果地圖項目物件包含這裡未列出的其他成員,BigQuery 會將這些成員直接轉換為資料表欄。
您可以使用 bq 指令列工具的 bq
load
指令,載入以換行符號分隔的 GeoJSON 檔案,如下所示:
bq load \ --source_format=NEWLINE_DELIMITED_JSON \ --json_extension=GEOJSON \ --autodetect \ DATASET.TABLE \ FILE_PATH_OR_URI
更改下列內容:
DATASET
是您的資料集名稱。TABLE
是目標資料表的名稱。FILE_PATH_OR_URI
是本機檔案或 Cloud Storage URI 的路徑。
上述範例會啟用結構定義自動偵測功能。如要進一步控管 BigQuery 如何轉換 properties
物件中的值,您可以改為提供明確的結構定義。詳情請參閱「指定結構定義」。如果您提供明確的結構定義,請勿在結構定義中加入頂層 type
資料欄。針對 properties
成員的每個成員,定義個別的資料欄,而非單一巢狀資料欄。
根據 RFC 7946 的定義,完整的 GeoJSON 資料結構是單一 JSON 物件。許多系統會將 GeoJSON 資料匯出為單一 FeatureCollection
物件,其中包含所有幾何圖形。如要將這類格式載入 BigQuery,您必須移除根層級 FeatureCollection
物件,並將個別特徵物件拆分為個別行,以便轉換檔案。舉例來說,下列指令會使用 jq
指令列工具,將 GeoJSON 檔案分割為以換行符號分隔的格式:
cat ~/file1.json | jq -c '.features[]' > converted.json
從以換行符號分隔的 GeoJSON 檔案建立外部資料表
您可以建立外部資料表,查詢儲存在 Cloud Storage 以換行符號分隔的 GeoJSON 檔案。如要建立外部資料表,請使用 CREATE EXTERNAL TABLE
DDL 陳述式。在 OPTIONS
子句中,將 format
選項設為 NEWLINE_DELIMITED_JSON
,並將 json_extension
選項設為 GEOJSON
。
範例:
CREATE EXTERNAL TABLE mydataset.table1 OPTIONS (
format="NEWLINE_DELIMITED_JSON",
json_extension = 'GEOJSON',
uris = ['gs://mybucket/geofile.json']
);
載入 GeoJSON 幾何圖形資料
地理空間分析支援載入以文字字串形式嵌入其他檔案類型的個別 GeoJSON 幾何物件。舉例來說,您可以載入 CSV 檔案,其中一個欄位包含 GeoJSON 幾何圖形物件。
如要將這類 GeoJSON 資料載入 BigQuery,請提供結構定義,為 GeoJSON 資料指定 GEOGRAPHY
資料欄。您必須手動提供結構定義。否則,如果啟用自動偵測功能,BigQuery 會將資料載入為 STRING
值。
地理空間分析不支援使用這種方法載入 GeoJSON 特徵物件或特徵集合。如果您需要載入地圖項目物件,建議使用以換行符號分隔的 GeoJSON 檔案。
如要將 GeoJSON 資料串流至具有 GEOGRAPHY
欄的現有 BigQuery 資料表,請在 API 要求中將資料序列化為字串。
bq
執行 bq 指令列工具 insert
指令:
echo '{"geo": "{\"type\": \"LineString\", \"coordinates\": [[-118.4085, 33.9416], [-73.7781, 40.6413]]}"}' \
| bq insert my_dataset.geo_table
Python
在嘗試這個範例之前,請先按照 BigQuery 快速入門:使用用戶端程式庫中的 Python 設定說明進行操作。詳情請參閱 BigQuery Python API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。詳情請參閱「設定用戶端程式庫的驗證機制」。
您也可以使用 ST_GEOGFROMGEOJSON
函式,將 GeoJSON 幾何物件轉換為 GEOGRAPHY
值。例如,您可以將幾何圖形儲存為 STRING
值,然後執行呼叫 ST_GEOGFROMGEOJSON
的查詢。
載入 GeoParquet 檔案
GeoParquet 是一種規格,可將地理空間類型新增至 Parquet 檔案格式。GeoParquet 包含中繼資料,可為內含的地理空間資料提供明確的語義,避免其他地理空間資料格式發生的解讀問題。
載入 Parquet 檔案時,BigQuery 會檢查 GeoParquet 中繼資料。如果有 GeoParquet 中繼資料,BigQuery 會預設將其描述的所有資料欄載入對應的 GEOGRAPHY
資料欄。如要進一步瞭解如何載入 Parquet 檔案,請參閱「載入 Parquet 資料」。
從 GeoParquet 資料建立外部資料表
參照 GeoParquet 檔案的外部資料表會將相關欄對應至 GEOGRAPHY
類型。
系統不會使用 GeoParquet 檔案 (bbox
、covering
) 中的統計資料,加快對外部資料表的查詢。
座標系與邊緣
在地理空間分析中,點是指 WGS84 球體表面上的地理位置,以經度和大地緯度的方式表示。至於邊緣 (edge) 則是指兩端點之間的球面測地線,也就是邊是球體表面上的最短路徑)。
WKT 格式並不提供座標系。載入 WKT 資料時,地理空間分析會假設資料使用 WGS84 座標,且具有球形邊緣。請確認來源資料與該座標系統相符,除非地理區域很小,可以忽略球面和平面邊緣之間的差異。
GeoJSON 明確使用 WGS84 座標與平面邊緣。載入 GeoJSON 資料時,地理空間分析會將平面邊緣轉換為球面邊緣。地理空間分析會視需要為線條加入額外的資料點,以便讓轉換後的邊緣序列維持在原始線條的 10 公尺範圍之內。這項程序稱為「平鋪」或「非均勻緻密化」。您無法直接控制平鋪處理程序。
如要載入具有球形邊緣的地理位置,請使用 WKT。如要載入具有平面邊緣的地理位置 (通常稱為「幾何圖形」),最簡單的方法就是使用 GeoJSON。不過,如果幾何資料已採用 WKT 格式,另一個做法是將資料載入為 STRING
類型,然後使用 ST_GEOGFROMTEXT
函式轉換為 GEOGRAPHY
值。將 planar
參數設為 TRUE
,即可將資料解讀為平面。
GeoParquet 檔案包含用來建立資料的座標系統和邊界中繼資料。讀取具有平面邊緣的 GeoParquet 檔案時,地理空間分析會將平面邊緣轉換為球面邊緣。系統會拒絕使用 WGS84 以外的座標系統的 GeoParquet 檔案。
選擇互換格式時,請務必瞭解來源資料使用的座標系統。多數系統會明確支援從 WKT 解析地理 (而非幾何圖形),或是採用平面邊緣。
您的座標應該先列出經度,再列出緯度。如果地理位置具有任何長線段或邊緣,則它們必須經過曲面細分處理,否則地理空間分析會將其詮釋為球形測地線,因此可能會無法對應至原始資料來源的座標系。
多邊形方向
在球體上,每個多邊形都有一個互補的多邊形。舉例來說,描述地球各大洲的多邊形會有一個描述地球海洋的多邊形。由於兩個多邊形都使用相同的界線環形描述,因此需要規則來解決在兩個多邊形中的模糊性 (兩個多邊形中,哪一個由指定的 WKT 字串描述)。
從檔案或透過串流攝入功能載入 WKT 和 WKB 字串時,地理空間分析會假設輸入中的多邊形方向如下:如果您按照輸入頂點的順序穿越多邊形界線,多邊形的內部會在左側。地理空間分析在將地理位置物件匯出至 WKT 和 WKB 字串時,會使用相同的規則。
如果您使用 ST_GeogFromText
函式將 WKT 字串轉換為 GEOGRAPHY
值,oriented
參數會指定函式判斷多邊形的方式:
FALSE
:將輸入內容解譯為具有較小面積的多邊形。這是預設行為。TRUE
:請使用前述的左側方向規則。這個選項可讓您載入面積大於半球的多邊形。
由於 GeoJSON 字串是在平面地圖上定義,即使輸入內容未遵照 GeoJSON 格式規範 (RFC 7946) 中定義的方向規則,也可以明確地判定方向。
處理格式不正確的空間資料
將其他工具的空間資料載入至 BigQuery 時,可能會因無效的 WKT 或 GeoJSON 資料而發生轉換錯誤。像是 Edge K has duplicate vertex with edge N
的錯誤,即表示多邊形具有重複的頂點 (除第一個與最後一個以外)。
為避免格式化問題,您可以建立一個函式讓輸出結果符合標準。舉例來說,匯出 PostGIS 資料時,您可以使用 PostGIS ST_MakeValid
函式將輸出內容標準化。您也可以將資料匯入為文字,然後呼叫 ST_GEOGFROMTEXT
或 ST_GEOGFROMGEOJSON
,並使用 make_valid
參數進行轉換。當 make_valid
為 TRUE
時,這些函式會嘗試修復無效的多邊形。
如要查找或忽略格式不正確的資料,請使用 SAFE
前綴函式輸出有問題的資料。例如,下列查詢使用 SAFE
前置字元來擷取格式不正確的空間資料。
SELECT geojson AS bad_geojson FROM mytable WHERE geojson IS NOT NULL AND SAFE.ST_GeogFromGeoJson(geojson) IS NULL
限制
地理空間分析不支援下列地理空間格式中的功能:
- 三維幾何圖形。包括 WKT 格式的「Z」字尾,以及 GeoJSON 格式的高度座標。
- 線性參考系統。包括 WKT 格式的「M」字尾。
- 除了幾何圖形基本元素或多部分幾何圖形以外的 WKT 幾何圖形物件。具體來說,地理空間分析僅支援 Point、MultiPoint、LineString、MultiLineString、Polygon、MultiPolygon 和 GeometryCollection。
如要瞭解 GeoJson 和 WKT 輸入格式專屬的限制條件,請參閱 ST_GeogFromGeoJson
和 ST_GeogFromText
。
將地理空間光柵資料與 Google Earth Engine 整合
地理空間洞察資料通常以格狀或光柵格式呈現。影像資料會將區域連續資料 (例如衛星圖像、天氣預報和土地覆蓋) 整理成像素格狀。雖然 BigQuery 主要專精於以表格形式呈現的向量資料,用於表示具有邊界和點的要素,但您可以使用 ST_REGIONSTATS
函式,將光柵資料整合至 BigQuery 分析。這個函式會使用 Google 的光柵分析平台 Earth Engine,針對光柵資料執行運算和匯總作業,以強化地理空間分析。詳情請參閱「使用光柵資料」。
如要瞭解如何將 Earth Engine 資料匯出至 BigQuery,請參閱「匯出至 BigQuery」。如要進一步瞭解 Earth Engine 和 BigQuery 之間的整合功能,請參閱 Earth Engine 說明文件中的「BigQuery 整合」一節。
轉換地理空間資料
如果您的資料表包含獨立的經度與緯度資料欄,則可以使用 GoogleSQL 地理位置函式 (例如 ST_GeogPoint
),將這些值轉換為地理位置。舉例來說,如果您有兩個 DOUBLE
欄位分別存放經度與緯度,則可以使用下列查詢建立一個地理位置欄位:
SELECT *, ST_GeogPoint(longitude, latitude) AS g FROM mytable
BigQuery 可將 WKT 和 GeoJSON 字串轉換成地理位置類型。如果資料採用的是其他格式 (例如 Shapefile),請使用外部工具將資料轉換為支援的輸入檔案格式 (例如 CSV 檔案),並將 GEOGRAPHY
欄編碼為 WKT 或 GeoJSON 字串。
將地理空間資料分區及分群
您可以將包含 GEOGRAPHY
資料欄的資料表分區和分群。GEOGRAPHY
資料欄可做為分群資料欄使用,但 GEOGRAPHY
資料欄無法當成分區資料欄。
如果您將 GEOGRAPHY
資料儲存在資料表中,且查詢使用空間述詞篩選資料,請確認資料表是以 GEOGRAPHY
欄為依據進行分群。這通常可提升查詢效能,或許還能降低成本。空間述詞會呼叫布林地理位置函式,並且會將 GEOGRAPHY
欄做為引數使用。以下範例顯示使用 ST_DWithin
函式的空間述元詞:
WHERE ST_DWithin(geo, ST_GeogPoint(longitude, latitude), 100)
將 JOIN 應用於空間資料
空間 JOIN 是指在 WHERE
子句中,將兩份具有述詞地理位置函式的資料表予以合併。例如:
-- 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
當您的地理位置資料保持不變時,空間合併的效果會更好。上述範例在查詢中建立了地理位置值,但若將地理位置值存入 BigQuery 資料表的話將會有更加的效能表現。
舉例來說,下列查詢會擷取經度與緯度組合,並且將它們轉換成地理資料點。執行這項查詢時,您可以指定新的目的地資料表來儲存查詢結果。
SELECT *, ST_GeogPoint(pLongitude, pLatitude) AS p FROM mytable
BigQuery 可透過下列 GoogleSQL 述詞函式,對 INNER JOIN 和 CROSS JOIN 運算子實作最佳化空間 JOIN:
下列項目的空間合併並未進行最佳化:
- LEFT、RIGHT 或 FULL OUTER 合併
- 如果涉及 ANTI 合併
- 當空間述詞為否定時
使用 ST_DWithin
述詞的 JOIN 只會在距離參數為常數運算式時最佳化。
匯出空間資料
當您從 BigQuery 匯出空間資料時,GEOGRAPHY
欄值將一律格式化成 WKT 字串。如要以 GeoJSON 格式匯出資料,請使用 ST_AsGeoJSON
函式。
如果用來分析匯出資料的工具無法解讀 GEOGRAPHY
資料類型,您可以使用地理函式 (例如 ST_AsText
或 ST_AsGeoJSON
),將資料欄值轉換為字串。地理空間分析會在必要時為線條加上額外的資料點,以便讓轉換後的邊緣序列維持在原始測地線的 10 公尺範圍之內。
例如,下列查詢使用 ST_AsGeoJSON
將 GeoJSON 值轉換為字串。
SELECT ST_AsGeoJSON(ST_MakeLine(ST_GeogPoint(1,1), ST_GeogPoint(3,2)))
結果資料會如下所示:
{ "type": "LineString", "coordinates": [ [1, 1], [1.99977145571783, 1.50022838764041], [2.49981908082299, 1.75018082434274], [3, 2] ] }
GeoJSON 線條擁有兩個額外的資料點。地理空間分析會新增這些資料點,這樣 GeoJSON 線條會和原始線條一樣貼近地面上的相同路徑。
後續步驟
- 如要開始使用地理空間分析,請參閱資料分析師專用的地理空間分析入門指南。
- 如要進一步瞭解地理空間分析的視覺化選項,請參閱「視覺化地理空間資料」。
- 如要查看地理空間分析中的 GoogleSQL 函式說明文件,請參閱「GoogleSQL 中的地理函式」。