Mapbox是新一代的地圖資料,只以媲美Google Map,且使用者不需付費,可以完全取代Google 地圖。缺點為地址有些是英文,有些是中文,待日後能更加完善。
Mapbox圖層
Mapbox共分為三個圖層
1. 底層 : base map,就是繪制地圖的地方。由 layout.mapbox.style定義
2. 軌跡層 : trace,繪製軌跡圖層,位於底層上方
3. 其它圖層 : 位於軌跡層上方,由 layout.mapbox.layers 定義更多圖層,為陣列格式。
存取權杖
請到 https://mapbox.com/ 註冊帳號,然後取得存取權杖(一組金鑰)。如果layout.mapbox.style不需從Mapbox service 使用資料的話,就不需權杖。
OpenStreetMap
此圖層樣式不需權杖。底下為簡易範例
import pandas as pd us_cities = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/us-cities-top-1k.csv") import plotly.express as px fig = px.scatter_mapbox(us_cities, lat="lat", lon="lon", hover_name="City", hover_data=["State", "Population"], color_discrete_sequence=["fuchsia"], zoom=4) fig.update_layout(mapbox_style="open-street-map") fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0}) fig.show()
COVID-19分佈圖
上面的資料,是plotly官方提供的,不太適合台灣學生的需求。所以本人提供一組台灣地圖的經緯度給大家測試,不過裏面的資料是假的啦,共57組經緯度。請注意,一開始要加 utf-8 coding 註明編碼方式,不然地址會出錯。註明編碼可用如下二種
# -*- coding:utf-8 -*-
或
# coding=utf-8
# -*- coding: utf-8 -*- import pandas as pd import plotly.express as px columns=['日期','經度','緯度','地區', '地址'] data=[['2022-04-07', 121.5573969, 25.03789526, '大安區', '台北市大安區仁愛路四段'], ['2022-04-07', 121.53266789, 25.03314581, '大安區', '台北市大安區'], ['2022-04-07', 121.53283231, 25.03268205, '大安區', '台北市大安區新生南路二段18號1樓'], ['2022-04-07', 121.53424816, 25.02165098, '大安區', '台北市大安區'], ['2022-04-07', 121.53374764, 25.01920939, '大安區', '台北市大安區新生南路三段70-76'], ['2022-04-07', 121.53353958, 25.01568478, '大安區', '台北市大安區羅斯福路四段'], ['2022-04-07', 121.53350407, 25.0157196, '大安區', '台北市大安區羅斯福路四段'], ['2022-04-07', 121.52574496, 25.02296225, '大安區', '台北市大安區台9線61號'], ['2022-04-07', 121.55070906, 25.04452193, '大安區', '台北市大安區市民大道四段106號'], ['2022-04-07', 121.55165104, 25.04441162, '大安區', '台北市大安區市民大道高架道路'], ['2022-04-07', 121.55165104, 25.04441162, '大安區', '台北市大安區市民大道高架道路'], ['2022-04-07', 121.55165104, 25.04441162, '大安區', '台北市大安區市民大道高架道路'], ['2022-04-07', 121.55271297, 25.04428248, '大安區', '台北市大安區市民大道四段'], ['2022-04-07', 121.55565248, 25.0445473, '大安區', '台北市大安區市民大道四段200號'], ['2022-04-07', 121.5574682, 25.04487821, '大安區', '台北市大安區市民大道四段244-280'], ['2022-04-07', 121.54604728, 25.01881104, '大安區', '台北市大安區基隆路三段'], ['2022-04-07', 121.5515982, 25.02342419, '大安區', '台北市大安區基隆路二段207號'], ['2022-04-07', 121.55167929, 25.02349392, '大安區', '台北市大安區基隆路二段'], ['2022-04-07', 121.55544567, 25.0215597, '大安區', '台北市大安區和平東路三段'], ['2022-04-07', 121.56443862, 25.01055636, '大安區', '台北市大安區和平東路三段'], ['2022-04-07', 121.55310062, 25.024025, '大安區', '台北市大安區和平東路三段410號'], ['2022-04-07', 121.54424859, 25.02493149, '大安區', '台北市大安區和平東路二段'], ['2022-04-07', 121.54183336, 25.02523993, '大安區', '台北市大安區和平東路二段181號7樓'], ['2022-04-07', 121.54339141, 25.026785, '大安區', '台北市大安區復興南路二段'], ['2022-04-07', 121.52386341, 25.02693519, '大安區', '台北市大安區和平東路一段32號'], ['2022-04-07', 121.5280697, 25.02659052, '大安區', '台北市大安區和平東路一段162-166'], ['2022-04-07', 121.53963584, 25.02533834, '大安區', '台北市大安區和平東路二段90號'], ['2022-04-07', 121.548982, 25.0253567, '大安區', '台北市大安區敦化南路二段275-265'], ['2022-04-07', 121.5486089, 25.03979522, '大安區', '台北市大安區敦化南路1段252號號'], ['2022-04-07', 121.54846285, 25.02178302, '大安區', '台北市大安區敦化南路二段218-228'], ['2022-04-07', 121.55369739, 25.01364592, '大安區', '台北市大安區黎元里'], ['2022-04-07', 121.53791678, 25.02320801, '大安區', '台北市大安區建國南路二段269號'], ['2022-04-07', 121.53765361, 25.04099687, '大安區', '台北市大安區建國南路一段'], ['2022-04-07', 121.53024686, 25.02088824, '大安區', '台北市大安區台9線201號'], ['2022-04-07', 121.53024686, 25.02088824, '大安區', '台北市大安區台9線201號'], ['2022-04-07', 121.54358767, 25.02638517, '大安區', '台北市大安區復興南路二段235號'], ['2022-04-07', 121.5438715, 25.03950497, '大安區', '台北市大安區合同興大樓'], ['2022-04-07', 121.53910544, 25.03357252, '大安區', '台北市大安區信義路三段109-5號'], ['2022-04-07', 121.53490588, 25.04480277, '大安區', '台北市大安區市民大道三段134號'], ['2022-04-07', 121.55061049, 25.0414445, '大安區', '台北市大安區忠孝東路四段建成大廈'], ['2022-04-14', 121.55245294, 25.03597355, '大安區', '台北市大安區安和路一段'], ['2022-04-14', 121.52782885, 25.02869865, '大安區', '台北市大安區潮州街117號'], ['2022-04-14', 121.53294365, 25.03240886, '大安區', '台北市大安區新生南路二段22號'], ['2022-04-14', 121.53159313, 25.02328384, '大安區', '台北市大安區雲和街'], ['2022-04-18', 121.52336976, 25.02852495, '大安區', '台北市大安區杭州南路二段93巷25號'], ['2022-04-18', 121.52430498, 25.03005497, '大安區', '台北市大安區潮州街55巷33號'], ['2022-04-18', 121.52574624, 25.02968839, '大安區', '台北市大安區金山南路二段132巷8號'], ['2022-04-18', 121.53191285, 25.02757371, '大安區', '大安區青田街8號'], ['2022-04-18', 121.53238689, 25.02909477, '大安區', '台北市大安區新生南路二段46巷50號'], ['2022-04-18', 121.53608385, 25.03458723, '大安區', '台北市大安區仁愛路三段24巷'], ['2022-04-18', 121.53747078, 25.03595963, '大安區', '台北市大安區建國南路一段'], ['2022-05-04', 121.55287565, 25.04346032, '大安區', '臺北市大安區敦化南路一段161巷77號'], ['2022-05-04', 121.55346692, 25.04405735, '大安區', '臺北市大安區市民大道四段178號'], ['2022-05-04', 121.55296431, 25.04347801, '大安區', '臺北市大安區忠孝東路四段223巷63號'], ['2022-05-04', 121.55668222, 25.03891804, '大安區', '臺北市大安區光復南路308巷18號'], ['2022-05-04', 121.55184198, 25.03900724, '大安區', '臺北市大安區仁愛路四段151巷15號'], ['2022-05-04', 121.55243225, 25.03344317, '大安區', '臺北市大安區安和路一段118號']]
df=pd.DataFrame(data=data, columns=columns) fig = px.scatter_mapbox(df, lat="緯度", lon="經度", hover_name="日期", hover_data=["地區", "地址"], color_discrete_sequence=["fuchsia"], zoom=12) fig.update_layout(mapbox_style="open-street-map") fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0}) fig.show()
strees樣式
上述的open-street-map樣式,說真的超醜的。其實有另一個精美的地圖,叫 “strees”。此地圖樣式需要權杖,所以請先到mapbox官網申請帳號及權杖。
底下代碼,會存取本站的資料庫,其帳號密碼將於上課時公佈。在此不予公告,敬請見諒。
完整代碼及範例如下
import pandas as pd import mysql.connector as mysql import plotly.express as px import plotly pd.set_option('display.max_columns', None) pd.set_option('display.max_rows', None) pd.set_option('display.width', None) pd.set_option('display.max_colwidth', None) conn=mysql.connect(host="ip", user='帳號', password='密碼', database='cloud') cursor=conn.cursor() cmd="select * from covid19" cursor.execute(cmd) columns = [] description = cursor.description for d in description: columns.append(d[0]) rs=cursor.fetchall() data=[] for r in rs: data.append(r) df=pd.DataFrame(data=data, columns=columns) px.set_mapbox_access_token("pk.xxxxx...........NFs6Tw") #請申請權杖 fig = px.scatter_mapbox(df, lat="lat", lon="lng", hover_name="cov_date", hover_data=["area", "address"], color_discrete_sequence=["fuchsia"], zoom=10) #fig.update_layout(mapbox_style="open-street-map") fig.update_layout(mapbox_style="streets") fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0}) plotly.offline.plot(fig, filename='mapbox_1.html', auto_open=False) fig.show()
底下的地圖,是不是精美多了呢!! 比較麻煩的是要申請權杖,但不用錢啊!!
Plotly
使用plotly也可以繪制mapbox,而且可以更改makers。
hoverinfo 為滑鼠移入時,要顯示的資料。在 go.Scattermapbox 裏,可以填入 lat,lng,text,name 四個參數,所以如果要顯示地址的話,就把地址放在 addr 的 list 中,然後把 text 指向 addr,hoverinfo 再指向 text
import pandas as pd import plotly import plotly.express as px
import numpy as np pd.set_option('display.max_columns', None) pd.set_option('display.max_rows', None) pd.set_option('display.width', None) pd.set_option('display.max_colwidth', None) import mysql.connector as mysql conn=mysql.connect(host='ip', user='account', password='password', database='cloud') cursor=conn.cursor() cmd="select * from covid19" cursor.execute(cmd) rs=cursor.fetchall() d=[r[1].strftime("%Y-%m-%d") for r in rs] lat=np.array([r[3] for r in rs]) lng=np.array([r[2] for r in rs]) addr=[r[5] for r in rs] import plotly.graph_objects as go token="pk.eyJ......iZfVw" # 自已申請 #symbol : 有一些預設的圖,但有的不能用 # symbol 網址 : 有些不能用。https://labs.mapbox.com/maki-icons/ fig=go.Figure(go.Scattermapbox( lat=lat, lon=lng, mode='markers', text=addr,
hovertext=addr,#可以是外面的list資料
hoverinfo='text',#只能使用 lat, lon, text, name四個選項 marker=dict(symbol='rocket', size=20),
#cluster=dict(enabled=True)#群組,相近的點成一群,mode及marker 必需取消才有效 )) fig.update_layout( hovermode='closest', mapbox=dict( accesstoken=token, bearing=0,#旋轉 center=go.layout.mapbox.Center( lat=lat.mean(), lon=lng.mean() ), zoom=10, ), mapbox_style='streets', margin={"r":0, "l":0, "t":0, "b":0} ) fig.show()
todo
''' airfield airport alcohol-shop amusement-park aquarium art-gallery attraction bakery bank bar beer bicycle bicycle-share bus cafe campsite car castle cemetery cinema circle circle-stroked clothing-store college dentist doctor dog-park drinking-water embassy entrance fast-food ferry fire-station fuel garden golf grocery harbor heliport hospital ice-cream information laundry library lodging marker monument mountain museum music park pharmacy picnic-site place-of-worship playground police post prison rail rail-light rail-metro religious-christian religious-jewish religious-muslim restaurant rocket school shop stadium star suitcase swimming theatre toilet town-hall triangle triangle-stroked veterinary volcano zoo '''
todo