iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 5
0

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

大綱:

  • groupby
  • spatial join
    • spatial join準備
    • spatial join操作
  • aggregation
  • dissolve

groupby

回顧這份資料,有district欄位表示行政區
(其實是路燈主管機關啦,但我們先當作行政區...)

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

Screen Shot 2018-10-19 at 23.37.11.png

GeoPandas這部分跟Pandas一樣,
我們可以用groupy做資料的的聚合

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

Screen Shot 2018-10-19 at 23.53.55.png

除了屬性上的grouping,
如果原始的GIS資料中沒有這樣可以grouping的屬性
我們可以拿統計單元或是鄉鎮市區等基本圖資做spatial join達到聚合的效果

spatial join

spatial join準備

就以前幾天的圖書館資料為例,我們拿村里界圖作為空間單元,
透過spatial join達到聚合效果。

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

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

把村里界圖讀進來GeoDataFrame

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是村里

藉著把圖書館資料讀進來

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 幾何資料基本運算

spatial join操作

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

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)

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,達到前面的效果

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

Screen Shot 2018-10-20 at 12.12.01.png

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

result.plot('ADMIT')

Screen Shot 2018-10-20 at 12.12.15.png

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

aggregation

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

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上色

aggre_v.plot('count')

Screen Shot 2018-10-20 at 12.19.37.png

dissolve

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

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


上一篇
Day04 幾何資料基本運算
下一篇
Day06 其它資料聚合與geohash
系列文
30天精通GIS資料分析-使用Python30

尚未有邦友留言

立即登入留言