# 2019_11_2_天氣資料結合地圖套件
## 氣象資料
###### tags: `讀書會` `python` `folium套件`
### Dataset
資料來源:https://data.gov.tw/dataset/9176
名稱:自動氣象站-氣象觀測資料
資料網址:https://opendata.cwb.gov.tw/api/v1/rest/datastore/O-A0001-001?Authorization=rdec-key-123-45678-011121314
大家可以先簡單看一下這個資料集的樣子,這個是一個及時的API回傳。也就是觀測站的數據,會固定時間回傳,並且更新在這個網址上。
而我們今天要做的,就是及時的取用這個資料,並且將這個資料做一些計算,並且視覺化。
### Data的樣子
這個Data是一個[JSON](https://zh.wikipedia.org/wiki/JSON)格式,也就是JavaScript Object Notation。這種格式適合用在網頁的傳輸上,也就是適合前端運用javascript去解析。
他的長相,很像是洋蔥,也就是一層一層的。以Python來說,可以想像是list以及dictionary的混合使用。
<pre>
import requests
import json
import folium #畫地圖套件
url = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/O-A0001-001?Authorization=rdec-key-123-45678-011121314"
req = requests.get(url) #method:get 去到頁面
json_content = req.content.decode('utf-8')
jason_dict = json.loads(json_content) #轉成字典了 補充兩者差異:load 開檔案 loads 純文字
m = folium.Map((23.770876, 120.934757), zoom_start= 8 )
for location in jason_dict['records']['location']:
folium.Marker(
location=[location['lat'], location['lon']],
popup=location['locationName'] + ' :' + location['weatherElement'][3]['elementValue'],
icon=folium.Icon(color='blue')
).add_to(m)
m.save('test.html')
</pre>
### 延伸練習題目#*1*
#### 超過平均給紅色icon低於平均給藍色icon
計算平均數
<pre>
#算平均數
temp = []
for x in jason_dict['records']['location']:
temp.append(float(x['weatherElement'][3]['elementValue']))
avtemp = float(sum(temp))/len(temp)
</pre>
加入if的判斷式
<pre>
for location in jason_dict['records']['location']:
if float(location['weatherElement'][3]['elementValue']) >= avtemp:
folium.Marker(
location=[location['lat'], location['lon']],
popup=location['locationName'] + ' 氣溫:' + location['weatherElement'][3]['elementValue'],
icon=folium.Icon(color='red')
).add_to(m)
else:
folium.Marker(
location=[location['lat'], location['lon']],
popup=location['locationName'] + ' :' + location['weatherElement'][3]['elementValue'],
icon=folium.Icon(color='blue')
).add_to(m)
</pre>
### if 的寫法太過冗長~在python中有精簡的寫法
將if直接寫在變數後面
<pre>
location['weatherElement'][3]['elementValue'],
icon=folium.Icon(color='red' if float(location['weatherElement'][3]['elementValue']) >= avtemp else 'blue')
).add_to(m)
</pre>
### 可以修改地圖樣式
可以在建立地圖地方修改地圖樣式
地圖樣式查詢網址: https://python-graph-gallery.com/288-map-background-with-folium/
<pre>
m = folium.Map((23.770876, 120.934757), tiles='Stamen Terrain', zoom_start= 8 )
</pre>
### 修改icon樣式
icon查詢網址:https://fontawesome.com/icons?d=gallery
<pre>
Icon(color='blue', icon_color='white', icon='info-sign', angle=0, prefix='glyphicon', **kwargs)
</pre>
### 顏色限制問題
由於icon本身顏色只能設定為下列:
'red', 'blue', 'green', 'purple', 'orange', 'darkred','lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue','darkpurple', 'white', 'pink', 'lightblue', 'lightgreen','gray', 'black', 'lightgray'
icon內部顏色可以以色碼表示
所以改由icon內部顏色表示為溫度
#### 所需套件
導入套件將RGB色碼轉成HEX表示
<pre>
from colormap import rgb2hex
</pre>
自刻氣溫轉RGB色碼的套件
<pre>
def temp2rgb(c):
rgbt = (c + 0)/30*765 #括號內要依據最低溫修改,外側為最大溫差
#計算R
r = rgbt - 255
if r <= 0:
r = 0
elif r >= 255:
r = 255
#計算G
g = 765 - rgbt
if g >= 255:
g = 255
elif g <= 0:
g = 0
#計算B
b = 255 - rgbt
if b <= 0:
b = 0
elif b >= 255:
b = 255
return r, g, b
</pre>
### 成品敘述
讀取台灣氣象資料,並標示於地圖上,地圖以地形表示
icon中箭頭方向表示風向,顏色表示為氣溫
#### 用途:觀測地形對於風向以及氣溫的影響
### 程式碼:
<pre>import requests
import json
import folium #畫地圖套件
from colormap import rgb2hex
def temp2rgb(c):
rgbt = (c + 0)/30*765 #括號內要依據最低溫修改,外側為最大溫差
#計算R
r = rgbt - 255
if r <= 0:
r = 0
elif r >= 255:
r = 255
#計算G
g = 765 - rgbt
if g >= 255:
g = 255
elif g <= 0:
g = 0
#計算B
b = 255 - rgbt
if b <= 0:
b = 0
elif b >= 255:
b = 255
return r, g, b
url = "https://opendata.cwb.gov.tw/api/v1/rest/datastore/O-A0001-001?Authorization=rdec-key-123-45678-011121314"
req = requests.get(url) #method:get 去到頁面
json_content = req.content.decode('utf-8')
jason_dict = json.loads(json_content) #轉成字典了 補充兩者差異:load 開檔案 loads 純文字
m = folium.Map((23.770876, 120.934757), tiles='Stamen Terrain', zoom_start= 8 )
#算平均數
temp = []
for x in jason_dict['records']['location']:
temp.append(float(x['weatherElement'][3]['elementValue']))
avtemp = sum(temp)/len(temp)
for location in jason_dict['records']['location']:
rgb=temp2rgb(float(location['weatherElement'][3]['elementValue']))
folium.Marker(
location=[location['lat'], location['lon']],
popup=folium.Popup(location['locationName'] + ' 時間:' + location['time']['obsTime'] + ' 氣溫:' + location['weatherElement'][3]['elementValue'], max_width=300,min_width=150),
icon=folium.Icon(color='darkred', icon='arrow-down', angle=int(location['weatherElement'][1]['elementValue']), icon_color=rgb2hex(int(rgb[0]), int(rgb[1]),int(rgb[2])))
).add_to(m)
m.save('test.html')</pre>