Python 練習: 以地圖顯示癌症死因資料(II)

根據前篇裡的說明,已經可以把癌症死亡資料裡的代碼都轉成實際文字,再把資料中"臺中市"的部份篩選出來。接下來,這篇要說明如何把資料在套疊在地圖上。有興趣的,也請參考 From Pandas to GeoPandas – 地理資料處理與分析 這篇,我也是從中獲益不少。

以Python來畫地圖資料,還有basemap這個套件。以前有試一下子basemap,但想拿來顯示地圖上的一些統計資料,似乎有點麻煩。最近才注意到有 geopandas這個套件,是 pandas 的擴充,pandas適合處理 csv 格式資料,再配合 geopandas,畫出"靜態"的資訊地圖非常簡單。為什麼強調是靜態?因為我過去顯示資料都是是開發OpenGL程式來完成的,OpenGL程式可以透過滑鼠/鍵盤做互動,如圈選物件,參數調整,也可以用動畫顯示連續資料。用Python想要達成相同功能,我目前Python功力還不夠,不知要如何做到。當然用 C/C++/OpenGL開發的難度及時間都會比較高,就要看需求做選擇了。

我在安裝 geopandas有遭遇一些問題,因為 geopandas 的 dependence,如GDAL、shapely、和fiona,用 pip install geopandas 時,要安裝這些相依套件一直無法成功。後來是直接去 https://www.lfd.uci.edu/~gohlke/pythonlibs/ 這裡分別下載 GDAL 和 fiona 的 .whl 來安裝,再用 pip install geopandas 才成功。
 


要畫出地圖,首先要得到各行政區邊界的資訊。從政府開放資料平臺可以得到行政區域界線圖資,這是以 shape file (shp)格式儲存。geopandas 可以直接讀取 shp 檔案。首先,載入需要的 module:

%pylab inline  #for displaying on jypyter notebook
pylab.rcParams['figure.figsize'] = (20.0, 20.0)
import geopandas as gpd
import pandas as pd

用 geopandas 載入 shape file,也是一行 code:

town_shp = gpd.read_file('../TW_TOWN_MOI_1070330/TOWN_MOI_1070330.shp')

檢視資料內容:

town_shp.head()

要畫出來,也是一行code就可以了:

town_shp.plot(cmap='RdBu')

篩選出"臺中市",並顯示台中行政區域:

taichung_town_shp=town_shp[town_shp['COUNTYNAME']=='臺中市']
taichung_town_shp.plot(cmap='RdBu')

接下來,載入(I) 得到的 "105_台中癌症死亡.csv" ,並找出只有口腔癌的部份:

cancer_data=pd.read_csv('../DataAnalysis/OpenData/DeathByCancer/105_台中癌症死亡.csv')
cancer_data_口腔癌=cancer_data[cancer_data['死因分類']=='口腔癌']

cancer_data_口腔癌.head()

把Unnamed, year, age_code, 死因分類這幾個不會用到的 colume 去掉:

cancer_data_口腔癌=cancer_data_口腔癌.drop(cancer_data.columns[[0,1,2,5]], axis=1)

再把屬於同一地區的口腔癌數目加總,

cancer_data_sum=cancer_data_口腔癌.groupby('鄉鎮市區').sum()
cancer_data_sum.head()

要注意的一件事,是上圖的結果,地區名變成 index了,在 index 欄裡的值無法作操作,所以要先把 index 複製成一個新的欄位,才能做操作。

cancer_data_sum['District']=cancer_data_sum.index
cancer_data_sum.head()

把'District'欄位中的前三個字('臺中市')去掉,就會只留下行政區名稱。

cancer_data_sum['District']=cancer_data_sum['District'].apply(lambda t: t[3:])
cancer_data_sum.head()

接下來要把 taichung_town_shp 和 cancer_data_sum 這兩個表格合併,前者是用 'TOWNNAME'欄位,後者是'District',照之前,用 merge 把兩個表格合併,並列出前五行:

Taichung_CancerDeathDistrict_口腔 = taichung_town_shp.merge(cancer_data_sum, left_on=('TOWNNAME'), right_on=('District'))
Taichung_CancerDeathDistrict_口腔.head()

選擇'N' 這欄位畫出來,

Taichung_CancerDeathDistrict_口腔.plot(column='N', cmap='OrRd')

由上圖可以觀察到並沒有把全台中市資料畫出來。檢查資料的結果,才發現口腔癌的數字,並沒有涵蓋台中市的行政區。用merge的話,沒有的行政區會被刪除,這不是我們想要的。

再上網查資料,發現應改用 join,這樣沒有資料的地方會用 na 填入,至少會保留該筆資料。改用 join 把兩個表合起來,後再把 na 的部份填入0。

left = taichung_town_shp.set_index('TOWNNAME')
right = cancer_data_sum.set_index('District')
Taichung_CancerDeathDistrict_口腔_1 = left.join(right)
Taichung_CancerDeathDistrict_口腔_1 = Taichung_CancerDeathDistrict_口腔_1.fillna(0)

這樣再來看顯示的結果如何,所有行政區域都有資料了。

Taichung_CancerDeathDistrict_口腔_1.plot(column='N', cmap='OrRd')

用 pysal 這模組函式,將口腔癌統計數字分成十個區間再畫出來,套用 Reds 這個顏色對照表:

import pysal
Taichung_CancerDeathDistrict_口腔_1.plot(column='N', k=10, cmap='Reds')

最後結果如下:

經過以上操作,得到口腔癌死亡數字在台中市的分佈圖。
 


兩篇文章,簡單的說明如何在將資料顯示於台灣地圖上。不過,因為過去開發的習慣,會想要能夠互動,例如滑鼠移到某個行政區域上時,可以列出那行政區域的數字。這種互動功能,也許還是得自己寫 OpenGL 來顯示資料才能做到吧。

1 thought on “Python 練習: 以地圖顯示癌症死因資料(II)”

  1. [i]加入斜體文字[/i]:(:(:o:o:lol::cry::cry:[i]加入斜體文字[/i][b]加入粗體文字[/b][b]加入粗體222文字[/b][i]加入斜體2文字[2/i2]2[b]加入粗體文字[/b]2222[b]加入粗體文字[/b][i]加入斜體文字[/i][url=網址]連結文字[/url][b]加入粗體文字[/b][url=網址]連結文字[/url][url=網址]連結文字[/url]

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。