鐵人賽2019 Day05 基本的資料聚合

  1. 1. spatial join
  2. 2. aggregation
  3. 3. dissolve
  4. 4. 後記

在Pandas可以使用groupby等方法進行資料聚合
例如先前第三天的路燈資料,如果想看一下不同的統計成果,除了空間上的展示外,可以用資料內的行政區欄位(district)做聚合

回顧這份資料,有district欄位表示行政區

1
2
light=gpd.read_file('output/light.shp',encoding='utf-8')
light

Screen Shot 2018-10-19 at 23.37.11.png

我們可以很簡單的用groupy做資料的的聚合

1
light.groupby('district').size()

Screen Shot 2018-10-19 at 23.53.55.png

如果資料中沒有這樣的屬性呢?(例如第三天的另一份圖書館點為資料)
在GIS資料中,我們可以對資料做空間聚合,聚合的單元可以是面資料。

路燈及圖書館資料請參考及Day03 從Pandas到Geopandas的幾種方法

spatial join

首先我們下載村里界圖
新北市政府資料開放平台,試著把圖書館資料與其做連結

把村里界圖讀進來,稍作觀察

1
2
3
4
import geopandas as gpd
village=gpd.read_file('data/Village/Village.shp',encoding='utf-8')
village.crs= {'init' :'epsg:3826'} # 避免資料沒設,這邊再重新給一次
village.head(3)

Screen Shot 2018-10-20 at 10.26.46.png
可以看出來ADMIV及ADMIT是村里與行政區

把圖書館資料有讀進來

1
2
3
4
lib=gpd.read_file('output/library.shp',encoding='utf-8')
lib.crs= {'init' :'epsg:4326'} # 避免資料沒設,這邊再重新給一次
lib=lib.to_crs(epsg=3826)
lib.head(3)

Screen Shot 2018-10-20 at 10.26.52.png
從上面可以看到,這份圖書館沒有行政區的資訊,無法直接產出如前面的統計表,但是由於我們有村里的GIS資料,可利用資料間的空間關係整合,在此特別在提醒,請記得轉換空間坐標,讓兩者系統一致喔。

坐標轉換請參考前一天的文章: Day04 幾何資料基本運算

先把他們套疊
(ps.為了方便顯示,只選擇中和區)

1
2
base=village[village['ADMIT']=='中和區'].plot(color='yellow')
lib[lib['address'].str.contains('中和區')].plot(ax=base)

Screen Shot 2018-10-20 at 10.35.02.png

從上得知,我們應該可以從空間關係取得我們要的東西,使用的是spatial join(sjoin)

1
2
result = gpd.tools.sjoin(lib, village[['ADMIV','ADMIT','geometry']], how="left")
result

Screen Shot 2018-10-20 at 10.38.35.png

其中,how是選擇要left join或是right, inner join,op則是空間關聯的方法,有contains, within, intersects可以選擇,我們選within,因為我們想計算點被包含在哪些村里界中

spatial join完成後,我們就可以做groupy,達到前面的效果

1
2
group=result.groupby(['ADMIT','ADMIV'])
group.size().reset_index(name='counts')

Screen Shot 2018-10-20 at 12.12.01.png

除了表格的展示,可以展點在圖上,並以行政區做上色

1
result.plot('ADMIT')

Screen Shot 2018-10-20 at 12.12.15.png

然而,如果要以地圖展示的話,可能不夠清楚,把村里的圖也納進來一起顯示吧!

aggregation

為了產生這樣的資訊,可以先計算village圖層涵蓋到的點數量,這之中會參考到昨天的幾何基本運算,這邊使用intersects,計算counts,也就是包含的點數量。

1
2
3
4
5
import numpy as np
counts=[np.sum(row['geometry'].intersects(lib.unary_union)) for idx, row in village.iterrows()]
village['count']=counts
aggre_v=village[['ADMIV','ADMIT','count','geometry']]
aggre_v[aggre_v['count']>0]

Screen Shot 2018-10-20 at 12.18.19.png

展示一下,並以count上色

1
aggre_v.plot('count')

Screen Shot 2018-10-20 at 12.19.37.png

dissolve

試著再把資料做一次聚合,使用行政區上色,會用到dissolve,其中第一個參數是要dissolve的欄位,aggfunc則是欄位中被合併的資料呈現的方式,我們這邊的聚合方式當然是sum

1
2
dis=aggre_v.dissolve('ADMIT',aggfunc='sum')
dis

Screen Shot 2018-10-20 at 12.22.27.png

最後,展示成果
Screen Shot 2018-10-20 at 12.23.01.png

後記

今天的練習在QGIS等軟體都可以很方便做到,在Geopandas中,也是透過幾行程式碼就可以操作到這些效果,並且更具彈性。

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