iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 6
0

前一天的資料聚合,所舉的應用例是行政區村里,實作簡單的點資料與空間單元做結合,然而事實上,聚合的單元不限於行政區村里,以台灣來說,可以使用內政部最小統計區的空間單元來做資料聚合(最小統計區與其發佈區的劃設主要是根據人口,有關最小統計區請參考最小統計區圖|MOI Open Data)。

另外,也有特別針對其他用途的統計區:經濟統計區圖資| 政府資料開放平臺,相關資料請自行參閱。

今天要介紹的也與昨日的資料聚合有一點關係(或是說他為空間索引)-geohash

Geohash

geohash故名意思是一種編碼,包含了多層級的架構,將空間劃分為網格(分為1-12層),Geohash的產生是根據Z-order curve的方式產生的,這樣的特性讓查詢上可以透過hash編碼的前綴來加快空間搜尋速度。

geohash被很常用在GIS資料的indexing上,他有點類似R-tree或Quadtree,
但geohash的索引編碼是固定的,可以用來做資料間的交換

以示意圖來理解geohash
687474703a2f2f692e737461636b2e696d6775722e636f6d2f74563953372e6a7067
(取自GitHub - stephenlb/geohash-chat-by-proximity: Geo Hashing Chat by Proximity to connect two or more users to a group chat.)

geohash的每個層級的網格的解析度大致如下:
1 5,009.4km x 4,992.6km
2 1,252.3km x 624.1km
3 156.5km x 156km
4 39.1km x 19.5km
5 4.9km x 4.9km
6 1.2km x 609.4m
7 152.9m x 152.4m
8 38.2m x 19m
9 4.8m x 4.8m
10 1.2m x 59.5cm
11 14.9cm x 14.9cm
12 3.7cm x 1.9cm

目前有一些工具可以檢視及瀏覽geohash,例如
Geohash encoding/decoding

若要瀏覽整體的geohash,可以參閱:
GeohashExplorer

將點資料映射到geohash

以下示範將點資料映射到geohash,達到類似聚合的效果

轉為經緯度

我們直接簡單從python做一些測試,geohash是透過經緯度坐標系統建構的:
路燈資料為例,先轉為經緯度資料

import geopandas as gpd
light=gpd.read_file('output/light.shp',encoding='utf-8')
light=light[light.is_valid]
light=light[light['district']=='永和區']
light.crs = {'init' :'epsg:3826'} 
light=light.to_crs(epsg=4326)
light

Screen Shot 2018-10-21 at 11.57.40.png

geohash編碼

接著,直接我們使用pygeohash,precision 7 代表第七層

須先安裝,使用 pip install python-geohash

import geohash
light['geohash']=[geohash.encode(row['geometry'].y,row['geometry'].x, precision=7) for idx,row in light.iterrows()]
light

Screen Shot 2018-10-21 at 12.08.16.png

聚合

從上面的步驟,現在每個點都有了一個geohash
我們可將geohash的編碼字串做groupby,聚合以降低資料量

group=light.groupby('geohash')
group=group.size().reset_index(name='counts')

Screen Shot 2018-10-21 at 12.12.37.png

為了呈現geohash聚合之成果,我們把geohash畫出來
先將每個聚合的geohash解碼,使用geohash.bbox(0)提供的geohash的四角邊界,
並把bbox轉為Polygon,把它存進去一個新的array中

from shapely.geometry import Polygon
geohashs=[]
for idx,row in group.iterrows():
    decoded=geohash.bbox(row['geohash'])
    geohashs.append(Polygon([(decoded['s'], decoded['w']), (decoded['s'],decoded['e']), (decoded['n'], decoded['e']), (decoded['n'],decoded['w'])]))

有了Polygon,就可以把geohash聚合的結果畫出來:

g = gpd.GeoSeries(geohashs)        
g_aggr = gpd.GeoDataFrame(group)
g_aggr['geometry']=g
g_aggr.plot('counts')

Screen Shot 2018-10-21 at 13.38.20.png

後記

透過今天的練習,利用geohash也可以進行網格式的資料聚合以及多時期的資料分析。

今天的相關測試可以參考GitHub


上一篇
Day05 基本的資料聚合
下一篇
Day07 進階幾何資料處理
系列文
30天精通GIS資料分析-使用Python30

尚未有邦友留言

立即登入留言