---
GA: UA-159972578-2
---
###### tags: `計量經濟` `地理資訊繪圖` `Econometrics` `Visualization` `tmap` `sf` `Map` `Geometry`
# 使用Tmap繪製地理資料地圖
## 地理資料的構成
1. 點:每一點(如房價、地標)
2. 線:線段(如道路、河流)
3. 面:區域(如村里、工業區等)
4. 網格:多使用於地形、自然資源,由每一網格所構成的一張圖(類似解析度)
而地理資料若加上當地區域或與四大資料有關的外接資料時,此時所能呈現在地圖上的效果將非常強大,而今日主角tmap便是讓功能放大的好套件。
## TGOS(地址轉經緯度服務平台)
+ 申請帳號後,可以申請[批次地址轉經緯度服務](https://www.tgos.tw/tgos/Web/Service/Apply/TGOS_Apply_Service.aspx?keyword=%E6%89%B9%E6%AC%A1%E5%9C%B0%E5%9D%80%E6%AF%94%E5%B0%8D%E6%9C%8D%E5%8B%99)
+ 批准後會得到一個API Key
+ 再到[批次門牌地址比對服務](https://www.tgos.tw/tgos/Web/Address/TGOS_Address.aspx)貼上API Key
+ 依照範本將地址資料整理成csv檔並上傳
+ 即可進行批次比對
# Tmap套件介紹
## 範例:高雄輕軌捷運沿線房價研究
![高雄輕軌捷運沿線房價研究](https://i.imgur.com/0MEHExc.jpg)
```{r}
# 台灣地理經緯度資料
load("geotw108.rdata") # twCounty:縣市資料 # twTown:鄉鎮市區資料 # twVill:里資料
county = st_simplify(twCounty,dTolerance=100) # 將地圖邊界變得較為平滑
# 高雄捷運輕軌線資料
L = st_read("kaoh/light_rail/LRT_1090102.shp", crs=3826) # 是"線"的要用3826
L = subset(L,LRTSYS=="高雄捷運") # 選取高雄捷運的路線
st_crs(L) # 檢查坐標系轉換是否成功
L = L %>% mutate_if(is.factor,as.character)
# 房產時價登錄資料
load("kaoh/house_price.rdata") # 在資料框中加入geometry的資訊
A = st_as_sf(D, coords=c("E","N"), crs=4326) %>% # "E"東經 "N"北緯
st_transform(crs=3826) # 當資料本身是經緯度時,不能直接轉3826,要先轉4326
# 計算房子到輕軌路線的距離
dx = st_distance(A, L) # 房子到輕軌的距離
dim(dx) # 49898筆資料,2條輕軌線
A$dx = apply(dx,1,min) # 房子到其中一條輕軌線的距離
range(A$dx) %>% round # 距離介於0-87104
# 篩選資料
Houses = A %>% filter(dx < 2000) %>% sample_n(1000) # 由於房屋的資料相當龐大,故進行抽樣
# 找出有輕軌穿過的行政區
Town = twTown[st_intersects(st_union(L), twTown)[[1]], ] # 回傳match到的行政區的index # st_union 將兩條輕軌線合併成一條
# 畫圖
subset(twVill, TOWN_ID %in% Town$TOWN_ID) %>%
tm_shape()+
tm_polygons("P_DEN", palette = "Greens", title="人口密度")+
tm_shape(Houses) +
tm_dots(col='type',size=0.7, alpha=0.8 ,n=8, title="房屋類型", palette = "Set3") +
tm_shape(L) +
tm_lines(col='LRTID',lwd=10,palette=c("green","orange"), title.col="輕軌路線") +
tm_shape(Town) + tm_borders(col="#925552", lwd = 4) +
tm_text(text="TOWN",col="#925552",size = 3) +
tm_layout(fontfamily="蘋方-繁 中黑體",
legend.title.size = 2,
legend.text.size = 1.3)
```
## 地理資料前置處理
### 資料介紹
+ X:各村里所得資料
+ D:各村里人口資料
+ X1 & D1:上述資料合併為區資料
+ T:各區所得與人口資料(即X+D)
+ TY:各區所得與人口資料(有分年分)
+ tt:各區界圖 (shapefile檔讀進來)
+ mfriver:台中土石流潛勢溪圖 (shapefile檔讀進來)
+ landmark:台中地標 (shapefile檔讀進來)
+ tair:台灣網格資料 (raster檔讀進來)
### 讀取資料
```{r}
#shapefile檔案讀法 #sf packege
tt = st_read("路徑/檔案名稱.shp")
#raster檔案讀法 #raster packege
tair = raster("路徑/檔案名稱.tif")
```
### 併入地理資訊
+ 資料型態:sf data frame
+ 定義了地理資料邊界(多邊形)
```{r}
pacman::p_load(purrr,dplyr,ggplot2,tidyr,plotly,stringr,googleVis,sf,sp,tmap,grDevices,raster,RColorBrewer)
# 土石流潛勢溪資料
mfr = mfriver %>% st_transform(,crs=4326) # 將區界資料轉成wgs84的坐標系
st_crs(mfr) # 確認坐標系是否轉成功
class(mfr) # 確認是否轉成sf object
any(duplicated(tt1$TOWNCODE)) # 檢查是否有重複值
```
```
## Coordinate Reference System:
## EPSG: 4326
## proj4string: "+proj=longlat +datum=WGS84 +no_defs"
```
> [1] "sf" "data.frame"
> [2] FALSE
+ Coordinate Reference System(CRS)座標投射方式
+ crs=4326
+ 方法:wgs84
+ 適用於經緯度資料
+ crs=3826:
+ 方法:TWD97
+ 適用於台灣地圖(計算兩地平面投影距離較準確)
+ 例如:探討瓦斯管線和房價的關係
+ 如果資料有經緯度(Global)資料,應該先把它用wgs84投射,將兩種資料合併後,再一起轉換成各國(Local)的平面地圖(經緯度的投射其實是球型,非平面)
## 繪製地圖(tmap)
### 小熱身
+ plot
通常適用於快速看一下圖形狀況時的便捷寫法
能快速看各欄分布狀況
```{r}
plot(TC,max.plot = 17)
```
![](https://i.imgur.com/oyhvkRX.png)
+ QTM
能快速疊圖
```{r}
qtm(TC)+qtm(tc_mfr)
```
![](https://i.imgur.com/7z4ErSb.png)
### 主要功能
和ggplot類似,需要基底(tm_shape),且可再疊上更多圖層元素(tm_fill or tm_dots)和地圖的邊界、美編與標示等。
#### 1. 地圖基底
```{r}
mapA=tm_shape(TC) + # 給予目標圖層
tm_fill() + # 填滿圖層工具
tm_borders() # 加邊界
# 可以用tm_polygon()取代tm_fill() + tm_borders(), 一次加兩個基底
```
<center>
![](https://i.imgur.com/wvDKNQL.png =60%x)
</center>
#### 2. 地圖美學
+ tm_fill() 顏色填法(style)介紹
1) cat:類別值,顏色各自特別
2) fixed:自訂區間
3) sd:標準差分法
4) pretty:從0開始,四捨五入(預設)
5) quantile:四分位數
6) jenks:抓出數值相近,並分出區間差異
7) log10_pretty:取對數
8) cont:在連續色塊呈現大量變色,適合網格資料
9) equal:分開均勻分布的變量
+ 調色盤(palette)概念
Tmap()系統顏色會依據欄位而有所變化:
![](https://i.imgur.com/hgJiBTt.png)
+ tm_layout() 可以設定字型
+ fontfamily="蘋方-繁 中黑體" (mac畫中文的好幫手~)
+ more detail: https://rdrr.io/cran/tmap/man/tm_layout.html
```{r}
map1 = tm_shape(TC) + # 給予目標圖層
tm_fill(col = "pop", # col 為顏色依據(資料或實際顏色)
alpha = 0.7, # 調整色彩濃度
style = "quantile", n=5, # style 可以調整圖例顏色區間規則(呈現的風格),預設為"pretty"
palette = "Oranges", # 調色盤
title = "Population") # 為圖例命名
map2 = tm_shape(TC) +
tm_fill(col = "pop",
style = "fixed",breaks= c(1.5e5,2.5e5,3.5e5,4.5e5,5.5e5,6.5e5,7.5e5,8.5e5,9.5e5,1e6),
palette = "Oranges",
title = "Population")
tmap_arrange(map1, map2) # 組圖檢視
```
![](https://i.imgur.com/VdqtAB9.png)
```{r}
mapx=tm_shape(TC)+
tm_borders(col ="grey40", # col 可設定顏色
lwd=2, # lwd 可設定邊界粗細
lty=2) # lty 可設定虛線
mapy=tm_shape(TC)+
tm_polygons("pop",
style = "quantile", # 自訂風格
n= 5, # 設定風格區間次數
palette = "BuGn", # 調色盤
title = "Population", # 新增標題
lwd=2,
lty=2) # tm_polygons 可包含tm_fill()與tm_borders的指令
```
![](https://i.imgur.com/khgWY3K.png)
```{r}
# 類別色塊
colA=tm_shape(TC) + tm_polygons("county")
# 連續色塊
colB=tm_shape(TC) + tm_polygons("pop", palette = "Blues")
# 顏色二分色塊
red_gray = brewer.pal(5,"RdGy") # 建立二分法的調色盤
colC=tm_shape(TC) + tm_polygons("pop", palette = red_gray)
```
![](https://i.imgur.com/dfdSs3L.png)
+ 圖標/比例尺
```{r}
map2 +
tm_compass(type="8star",position = c("left","top"))+ # 增加指北針與設定位置
tm_scale_bar(breaks= c(0,10,25), text.size = 0.7) # 增加比例尺
```
![](https://i.imgur.com/JtwJuBa.png)
+ 圖型周圍
```{r}
deco1= map2 + tm_layout(title = "Taichung Population") # 加上地圖標題
deco2= map2 + tm_layout(scale = 5) # 加粗所有框線
deco3= map2 + tm_layout(bg.color = "grey") # 背板上色
deco4= map2 + tm_layout(frame = F) # 移除外框
deco5= map2 + tm_layout(inner.margin = 0.2) # 圖型縮小
deco6= map2 + tm_layout(legend.position=c("left","bottom")) # 調整圖例位置
```
![](https://i.imgur.com/hCKQ9MZ.png)
+ 主題風格
```{r}
sty1 = map2+ tm_style("bw" ) # 灰階
sty2 = map2+ tm_style("classic") # 復古
sty3 = map2+ tm_style("cobalt" ) # 深色底白字
sty4 = map2+ tm_style("col_blind" ) # 色盲顏色調整
```
![](https://i.imgur.com/Dcy5awm.png)
#### 3. 疊圖
```{r}
TCG=tm_shape(TC)+tm_polygons() # 建立底圖
class(TCG)
```
> [1] "tmap"
```{r}
TCG +
tm_shape(landmark) + # 加入地標資料
tm_dots() + # 以點呈現 tm_dots()
```
![](https://i.imgur.com/3Q80xyz.png)
```{r}
#將剛剛所學來畫幾圖吧
TC1=TC[,-c(1:2)]
#台中人口分布
tm_shape(TC1)+
tm_symbols(col = "red", border.col = "white", size = "pop")+
tm_borders(col = "grey60",lwd = 0.5)+ tmap_mode("plot")
```
![](https://i.imgur.com/EB9D1hs.png)
```{r}
#台中地形與土石流潛勢區分布
TCH = TC %>% filter(county=="和平區")
tm_shape(TCH)+tm_polygons() +
tm_shape(tair)+ # 加入網格資料(tm_raster())
tm_raster(alpha=0.3) +
tm_shape(tc_mfr) + # 加入土石流潛勢溪圖
tm_lines(col="Potential",palette = "Blues")
```
![](https://i.imgur.com/0CpuI6v.png)
```{r}
#台中市各區平均收入
tm_shape(TC1) +
tm_fill(col="Income_mean",
palette = "Greens" ,
style = "quantile",n=7 ,
title = "台中平均收入",
alpha = 0.5) +
tm_borders(col = "grey60",lwd = 0.5) +
tm_text("county",size = 0.6)
```
![](https://i.imgur.com/xtLqJ6A.png)
#### 4. 多圖呈現
+ 法1:tmap_arrange()
+ 法2:facet()
```{r}
#當需要看年分變化時,可使用年份分法的地圖繪製
TYC_100_103= TYC %>% filter(year %in% c(100,101,102,103))
tm_shape(TC)+tm_polygons()+
tm_shape(TYC_100_103)+
tm_symbols(col = "red", border.col = "white", size = "pop") + #size為以大小來顯示(也可用tm_bubble)
tm_facets(by = "year", # by 變量來分圖
nrow = 2, # 以幾列來呈現(以可設定ncol))
free.coords = F)
```
![](https://i.imgur.com/GUgk22m.png)
+ 法3:grid::viewport
```{r}
#將台中、台南、台北畫在同一張圖
TC_map = tm_shape(TC, projection = 4326) + tm_polygons() +
tm_layout(frame = FALSE,inner.margin = 0.2)
TN_map = tm_shape(TN) + tm_polygons() +
tm_layout(title = "Tainan", frame = FALSE, bg.color = NA,
title.position = c("LEFT", "BOTTOM"))
TP_map = tm_shape(TP) + tm_polygons() +
tm_layout(title = "Taipei", frame = FALSE, bg.color = NA)
```
```{r}
library(grid)
TC_map
print(TN_map, vp = grid::viewport(0.5, 0.25, width = 0.25, height = 0.25))
print(TP_map, vp = grid::viewport(0.25, 0.2, width = 0.3, height = 0.3))
```
<center>
![](https://i.imgur.com/T9dJsgJ.png =60%x)
</center>
### 互動式地圖
```{r}
subset(twVill, TOWN_ID %in% Town$TOWN_ID) %>%
tm_shape()+
tm_polygons("P_DEN", palette = "Greens", title="人口密度", alpha = 0.5)+
tm_shape(L) +
tm_lines(col='LRTID',lwd=3,palette=c("green","orange")) +
tm_shape(Houses) +
tm_dots(col='age',size=0.05, alpha=0.9 ,n=8, title="屋齡", palette = "RdPu") +
tm_shape(Town) + tm_borders(col="gray") +
tm_text(text="TOWN",col="black" ) +
tmap_mode("view") # 讓地圖如ggplotly般也能成為互動式
```
![](https://i.imgur.com/ADqEUiM.png)
+ 同步縮放功能
```{r}
facets = c("pop", "male_ratio","female_ration")
tm_shape(TC) + tm_polygons(facets) +
tm_facets(nrow = 1, sync = TRUE)
```
![](https://i.imgur.com/Abuhg70.png)