Mapbox with plotly

      在〈Mapbox with plotly〉中留言功能已關閉

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

請參照官網 : https://plotly.com/python/mapbox-layers/