對有系統性的調查或監測而言,網格系統是選擇樣區時很常用到的工具。舉凡BBS、路殺社系統化調查等。除此之外,在時空資料的視覺化,網格系統也是很常用的輔助工具。在 QGIS 跟 ArcGIS 內都有相對應的工具來產生網格系統 (QGIS 內叫 Vector grid,ArcGIS 應該是 Fishnet),不過當要產生的網格數量比較多的時候 (e.g. 台灣含東沙南沙的 1 x 1 公里網格),用 R 來操作應該可以節省不少時間,至少把流程建在 code 中,當要重複做類似的事情時,不用一直在那邊點左鍵XD
以下範例為建置台灣範圍 (含離島) 坐標系統為 TWD97 121 的網格系統。為了讓最後呈現的圖示比較清楚,我們這邊建立的網格解析度設為 10 x 10 公里。
(註:本篇只探討方法,至於符不符合 TM2 這件事,就先不在這裡討論啦…:P)
# 安裝套件
list.of.packages <- c("sf", "rgdal", "magrittr", "maptools")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
# 讀入套件
library(sf) # for st_make_grid
library(rgdal) # for readOGR, writeOGR
library(magrittr) # for pipe
這篇示範的方法是以 sf 這個套件的函數為主,在這套建構網格系統方法中,有幾個必要的參數需要設定,包括網格系統的涵蓋範圍 (grid extent)、坐標系統 (coordinate system) 以及網格系統的解析度 (resolution),解析度要換算成欄跟列的網格數量。
網格系統的範圍 (grid extent) 是用 5 x 2 的 矩陣來指定, 順序依序為左上→右上→右下→左下→左上, 我們先透過台灣縣市界縣的範圍來確定網格系統的範圍。
TW.island <- readOGR("E:/for R markdown/mapdata", # 檔案路徑
"TOWN_MOI_1070516", # 檔案名稱
use_iconv = TRUE, # 允許設定encoding
encoding = "UTF-8") %>% # encoding設定為UTF-8
# 將圖層坐標系統轉成與欲設立的網格座標系統相符 (TWD97_121, epsg代碼為3826)
spTransform(CRS("+init=epsg:3826"))
TW.island@bbox
## min max
## x -40418.36 606875.6
## y 2422004.77 2919551.3
grid.extent <-
matrix(c(-50000, 2920000, # 左上 (Xmin, Ymax)
610000, 2920000, # 右上 (Xmax, Ymax)
610000, 2420000, # 右下 (Xmax, Ymin)
-50000, 2420000, # 左下 (Xmin, Ymin)
-50000, 2920000), # 左上 (Xmin, Ymax)
byrow = TRUE, ncol = 2) %>%
# 轉成list以符合st_polygon的需求
list() %>%
# 產生網格系統範圍的polygon
st_polygon() %>%
# 轉格式跟設置坐標系統
st_sfc(., crs = 3826)
這邊使用的是 sf package 的 st_make_grid()
,製作出來的網格系統格式為 sfc,所以還要透過 st_sf()
將網格轉成帶有屬性表的 sf 格式。因為後續在網格選取以及 spatial join 是透過 rgdal 的函數,所以要再用 as()
將網格資料轉成 SpatialPolygonDataFrame。
Grid.sys <-
# 製作網格系統
st_make_grid(grid.extent, # 網格系統的範圍:grid.extent
n = c(66, 50), # 網格系統的解析度:66欄 x 50列
crs = 3826, # 坐標系統:TWD97 121
what = 'polygons') %>% # 產出形式:polygon
# 轉成sf格式,並且創造ID欄位
st_sf('geometry' = ., data.frame('ID' = 1:length(.))) %>%
# 轉成sp格式
as(., 'Spatial') %>%
# 再指定一次座標系統,確保與台灣範圍的圖層一致
spTransform(CRS("+init=epsg:3826"))
Grid.TW <-
Grid.sys[subset(TW.island),] # 逗號不能省略
將台灣範圍圖層的鄉鎮資訊綁定到網格系統的屬性表中
TW_info <-
over(Grid.TW, TW.island) # creat a data.frame of IDs in IBA for 1km grid
Grid.TW@data %<>% cbind(., TW_info)
ID | TOWNID | TOWNCODE | COUNTYNAME | TOWNNAME | TOWNENG | COUNTYID | COUNTYCODE | |
---|---|---|---|---|---|---|---|---|
28 | 28 | T04 | 10013040 | 屏東縣 | 恆春鎮 | Hengchun Township | T | 10013 |
29 | 29 | T04 | 10013040 | 屏東縣 | 恆春鎮 | Hengchun Township | T | 10013 |
37 | 37 | V16 | 10014160 | 臺東縣 | 蘭嶼鄉 | Lanyu Township | V | 10014 |
93 | 93 | T04 | 10013040 | 屏東縣 | 恆春鎮 | Hengchun Township | T | 10013 |
94 | 94 | T04 | 10013040 | 屏東縣 | 恆春鎮 | Hengchun Township | T | 10013 |
95 | 95 | T04 | 10013040 | 屏東縣 | 恆春鎮 | Hengchun Township | T | 10013 |
102 | 102 | V16 | 10014160 | 臺東縣 | 蘭嶼鄉 | Lanyu Township | V | 10014 |
103 | 103 | V16 | 10014160 | 臺東縣 | 蘭嶼鄉 | Lanyu Township | V | 10014 |
159 | 159 | T32 | 10013320 | 屏東縣 | 獅子鄉 | Shizi Township | T | 10013 |
160 | 160 | T32 | 10013320 | 屏東縣 | 獅子鄉 | Shizi Township | T | 10013 |
writeOGR(Grid_island,
"E:/for R markdown", # out put directoty
"Grid_sys_tw", # name of shapefile
driver = "ESRI Shapefile") #file format