行政區範圍格點化

Table of contents

背景

  • 嚴格來說,這一篇應該不是放在GIS而是繪圖區(Graphics/NCL),因為所處理的檔案(gridLL.csv)只是為NCL繪製choropleth圖所需要的一個前處理檔。使用的程式mk_gridLL.py及產生公版模式格點鄉鎮名稱檔,也是放在NCL目錄下。
  • 然因為使用了shapely模組,所以技術上會歸併在GIS類別,與shape_to_raster是很類似的作業,只是靠著geojson資料庫與shapely模組,大大提升了程式碼的簡潔特性。
  • 簡言之,之前式直接處理shape檔案,而這個版本是處理geojson檔,有較多的支援。
  • 過去相關程式如mk_town.pymk_townNew.pyshape_to_rasterCAM-chem模式結果之校正應用
  • 同樣是前處理,將2維點陣線性化成為1維的工作表、以CSV儲存,似乎較符合直覺。

程式說明

IO’s

  • 作業目錄:/nas2/cmaqruns/2019TZPP/output/Annual/aTZPP/LGHAP.PM25.D001
  • 引數:無
  • 網格模板
    • 不限制是哪個範圍區位或解析度,只是要能夠與geojson檔匹配
    • 如此處為tempTW.nc,為公版台灣範圍,然解析度為1公里
  • geojson檔案:為內政部TOWN_MOI_1090727.shp轉成之geo.json檔。
  • 輸出檔案:gridLL.csv(如下)
            LAT         LON                                          Point  TOWNCODE COUNTYCODE COUNTYNAME TOWNNAME
3746  21.896349  120.859967   POINT (120.85996721123759 21.89634893493374)  10013040      10013        屏東縣      恆春鎮
4021   21.90574  120.850031   POINT (120.85003131220148 21.90574036131661)  10013040      10013        屏東縣      恆春鎮

網格設定

  • 將(y,x)之經緯度拉成1維的資料表,在用shapely的Point定義備用。
name='tempTW.nc'
nc = netCDF4.Dataset(fname,'r')
V=[list(filter(lambda x:nc.variables[x].ndim==j, [i for i in nc.variables])) for j in [1,2,3,4]]
nt,nlay,nrow,ncol=(nc[V[3][0]].shape[i] for i in range(4))
pnyc = Proj(proj='lcc', datum='NAD83', lat_1=nc.P_ALP, lat_2=nc.P_BET,lat_0=nc.YCENT, lon_0=nc.XCENT, x_0=0, y_0=0.0)
X=[nc.XORIG+nc.XCELL*i for i in range(ncol)]
Y=[nc.YORIG+nc.YCELL*i for i in range(nrow)]
x,y=np.meshgrid(X, Y)
x=x.flatten();y=y.flatten()
lon, lat = pnyc(x, y, inverse=True)
df=pd.DataFrame({'LAT':lat,'LON':lon})
df['Point']=[Point(i,j) for i,j in zip(lon,lat)]
ndf=len(x)
  • 此處的模板檔案並未限定解析度、因此適用於任何網格座標系統。但是前提是座標參數之相關屬性必須是正確的。
  • 因為IO都沒有網格名稱、解析度等等標記,使用者必須自行紀錄
    • LGHAP的解析度是1 Km
    • 公版模式解析度是3Km

行政區邊界線與ID之定義

  • geopandas能將複雜的shape檔內容,簡化成資料表,不論是單一或多個多邊形,在其資料表中只是一個單元gdf.geometry[:]。
  • 其內容如下
root='/nas1/Data/GIS/TWN_town/'
gdf = gpd.read_file(root+'TOWN_MOI_1090727_geo.json')
ngdf=len(gdf);ndf=len(df)
In [524]: gdf.head()
Out[524]:
  TOWNID  TOWNCODE COUNTYNAME TOWNNAME             TOWNENG COUNTYID COUNTYCODE                                           geometry
0    V02  10014020        臺東縣      成功鎮  Chenggong Township        V      10014  POLYGON ((121.40996 23.21351, 121.40988 23.213...
1    T21  10013210        屏東縣      佳冬鄉    Jiadong Township        T      10013  POLYGON ((120.57660 22.45775, 120.57655 22.457...
2    P13  10009130        雲林縣      麥寮鄉    Mailiao Township        P      10009  POLYGON ((120.29898 23.74093, 120.29898 23.741...
3    V11  10014110        臺東縣      綠島鄉      Ludao Township        V      10014  MULTIPOLYGON (((121.49155 22.67746, 121.49171 ...
4    V16  10014160        臺東縣      蘭嶼鄉      Lanyu Township        V      10014  MULTIPOLYGON (((121.61180 21.94290, 121.61236 ...

串連搜尋

  • 使用網格點之迴圈一一找出正確的行政區代碼(此處為gdf.TOWNCODE)
  • shapely的點Point本身就帶有within()的函數,其引數為(單一或多個)多邊形
townid=[]
for i in range(ndf):
  found=0
  for j in range(ngdf):
    if df.Point[i].within(gdf.geometry[j]):
      townid.append(gdf.TOWNCODE[j])
      found=1
      break
  if found==0:townid.append('00000000')
df['TOWNCODE']=townid

整併與輸出

tn={i:j for i,j in zip(gdf.TOWNCODE, gdf.TOWNNAME)}
cn={i:j for i,j in zip(gdf.COUNTYCODE, gdf.COUNTYNAME)}
cn.update({'00000':'海'})
tn.update({'00000000':'海'})
df['COUNTYCODE']=[i[:5] for i in df.TOWNCODE]
df['COUNTYNAME']=[cn[i] for i in df.COUNTYCODE]
df['TOWNNAME']=[tn[i] for i in df.TOWNCODE]
df.set_index('LAT').to_csv('gridLL.csv')

程式下載