作者:錢魏Way
原文:https://www.biaodianfu.com/folium.html
大家好,我是明哥。
今天給大家介紹一個非常 NB 的Python 庫,專門用來繪製地圖的,它叫 Folium 。
Folium是一個基於leaflet.js的Python地圖庫,其中,Leaflet是一個非常輕的前端地圖可視化庫。即可以使用Python語言調用Leaflet的地圖可視化能力。它不單單可以在地圖上展示數據的分布圖,還可以使用Vincent/Vega在地圖上加以標記。Folium可以讓你用Python強大生態系統來處理數據,然後用Leaflet地圖來展示。
Folium中有許多來自OpenStreetMap、MapQuest Open、MapQuestOpen Aerial、Mapbox和Stamen的內建地圖元件,而且支持使用Mapbox或Cloudmade的API密鑰來定製個性化的地圖元件。Folium支持GeoJSON和TopoJSON兩種文件格式的疊加,也可以將數據連接到這兩種文件格式的疊加層,最後可使用color-brewer配色方案創建分布圖。
2. Folium的使用地圖的生成imgfolium.folium.Map()詳解
folium.folium.Map(location=None, width='100%', height='100%', left='0%', top='0%', position='relative', tiles='OpenStreetMap', attr=None, min_zoom=0, max_zoom=18, zoom_start=10, min_lat=-90, max_lat=90, min_lon=-180, max_lon=180, max_bounds=False, crs='EPSG3857', control_scale=False, prefer_canvas=False, no_touch=False, disable_3d=False, png_enabled=False, zoom_control=True, **kwargs)
參數說明:
location (tuple or list, default None):緯度和經度
width (pixel int or percentage string (default: 『100%』)):地圖寬度
height (pixel int or percentage string (default: 『100%』)):地圖高度
tiles (str, default 『OpenStreetMap』) :瓦片名稱或使用TileLayer classass.
min_zoom (int, default 0):地圖可縮放的最小級別
max_zoom (int, default 18):地圖可縮放的最大級別
zoom_start (int, default 10) :地圖的初始縮放級別
attr (string, default None):當使用自定義瓦片時,傳入自定義瓦片的名詞
crs (str, default 『EPSG3857』) :投影坐標系標識
EPSG3857: Web墨卡託投影后的平面地圖,坐標單位為米。大部分國外地圖使用的時該標準。
EPSG4326: Web墨卡託投影后的平面地圖,但仍然使用WGS84的經度、緯度表示坐標。
EPSG3395: 墨卡託投影,主要用於航海圖
Simple: 簡單的x,y匹配,用於自定義瓦片(比如遊戲地圖)
control_scale (bool, default False) :是否在地圖上顯示縮放標尺
prefer_canvas (bool, default False):強制使用Canvas渲染
no_touch (bool, default False) :是否允許觸摸事件
disable_3d (bool, default False) :強制使用CSS 3D效果
zoom_control (bool, default True) :是否要限制zoom操作
**kwargs:Leaflets地圖類的其他參數: https://leafletjs.com/reference-1.5.1.html#map
「tiles」參數可選值:
「OpenStreetMap」
「Mapbox Bright」 (Limited levels of zoom for free tiles)
「Mapbox Control Room」 (Limited levels of zoom for free tiles)
「Stamen」 (Terrain, Toner, and Watercolor)
「Cloudmade」 (Must pass API key)
「Mapbox」 (Must pass API key)
「CartoDB」 (positron and dark_matter)
「tiles」的自定義設置:
img地球上同一個地理位置的經緯度,在不同的坐標系中,會有少量偏移,國內目前常見的坐標系主要分為三種:
地球坐標系——WGS84:常見於GPS設備,Google地圖等國際標準的坐標體系。
火星坐標系——GCJ-02:中國國內使用的被強制加密後的坐標體系,高德坐標就屬於該種坐標體系。
百度坐標系——BD-09:百度地圖所使用的坐標體系,是在火星坐標系的基礎上又進行了一次加密處理。
所以在設置「tiles」時需要考慮目前手中得經緯度屬於那種坐標系。
由於投影坐標系中沒有GCJ-02和BD-09對應的標識,所以在自定義瓦片時主要經緯度能匹配上,crs中的設置可保持不變。更多詳情介紹請看:瓦片坐標系學習
如果需要將地圖保存,只需執行:m.save(「map.html」) 即可。
添加點、線、面要素添加點
import folium
m = folium.Map(location=[39.917834, 116.397036], zoom_start=13, width='50%',height='50%', zoom_control='False',
tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}<ype=6',attr='AutoNavi')
tooltip ='請點擊我查看該點信息'
folium.Marker([39.937282,116.403187], popup='南鑼鼓巷',tooltip=tooltip).add_to(m)
folium.Marker([39.917834,116.397036], popup='故宮',tooltip=tooltip).add_to(m)
folium.Marker([39.928614,116.391746], popup='北海公園', tooltip=tooltip, icon=folium.Icon(color='red')).add_to(m)
folium.Marker([39.942143,116.382590], popup='後海公園', tooltip=tooltip, icon=folium.Icon(color='green', prefix='fa', icon='taxi')).add_to(m)
m
Folium.Icon類可以設置color, icon_color, icon, angle, prefix這5個參數:
color的可選項包括:[『red』, 『blue』, 『green』, 『purple』, 『orange』, 『darkred』, 『lightred』, 『beige』, 『darkblue』, 『darkgreen』, 『cadetblue』, 『darkpurple』, 『white』, 『pink』, 『lightblue』, 『lightgreen』, 『gray』, 『black』, 『lightgray』] ,或者HTML顏色代碼
icon_color同上
icon可以在Font-Awesome網站中找到對應的名字,並設置prefix參數為』fa』
angle以度為單位設置
其他:
m.add_child(folium.LatLngPopup()) #顯示滑鼠點擊點經緯度
m.add_child(folium.ClickForMarker(popup='Waypoint')) # 將滑鼠點擊點添加到地圖上
添加圓
folium.Circle(
radius=300,
location=[39.928614,116.391746],
popup='北海公園',
color='crimson',
fill=False,
).add_to(m)
folium.CircleMarker(
location=[39.942143,116.382590],
radius=50,
popup='後海公園',
color='#3186cc',
fill=True,
fill_color='#3186cc'
).add_to(m)
Circle和CircleMarker的不同:CircleMarker的radius一個單位是像素,Circle的一個單位時米
添加線段
folium.PolyLine([
[39.917834,116.397036],
[39.928614,116.391746],
[39.937282,116.403187],
[39.942143,116.382590]
],color='red').add_to(m)
添加多邊形
folium.Marker([39.917834,116.397036], popup='故宮').add_to(m)
folium.Marker([39.928614,116.391746], popup='北海公園').add_to(m)
folium.Marker([39.937282,116.403187], popup='南鑼鼓巷').add_to(m)
folium.Marker([39.942143,116.382590], popup='後海公園').add_to(m)
folium.Polygon([
[39.917834,116.397036],
[39.928614,116.391746],
[39.942143,116.382590],
[39.937282,116.403187],
],color='blue', weight=2, fill=True, fill_color='blue', fill_opacity=0.3).add_to(m)
在地圖上顯示前200條犯罪數據
import folium
import pandas as pd
san_map = folium.Map(location=[37.77, -122.42], zoom_start=12,width='50%',height='50%')
# cdata = pd.read_csv('https://cocl.us/sanfran_crime_dataset')
cdata = pd.read_csv('Police_Department_Incidents_-_Previous_Year__2016_.csv') #犯罪數據,包含犯罪所在經緯度
# get the first 200 crimes in the cdata
limit = 200
data = cdata.iloc[0:limit, :]
# Instantiate a feature group for the incidents in the dataframe
incidents = folium.map.FeatureGroup()
# Loop through the 200 crimes and add each to the incidents feature group
for lat, lng, in zip(cdata.Y, data.X):
incidents.add_child(
folium.CircleMarker(
[lat, lng],
radius=7, # define how big you want the circle markers to be
color='yellow',
fill=True,
fill_color='red',
fill_opacity=0.4
)
)
san_map.add_child(incidents)
統計區域犯罪總數
from folium import plugins
# let's start again with a clean copy of the map of San Francisco
san_map = folium.Map(location=[37.77, -122.42], zoom_start=12,width='50%',height='50%')
# instantiate a mark cluster object for the incidents in the dataframe
incidents = plugins.MarkerCluster().add_to(san_map)
# loop through the dataframe and add each data point to the mark cluster
for lat, lng, label, in zip(data.Y, data.X, cdata.Category):
folium.Marker(
location=[lat, lng],
icon=None,
popup=label,
).add_to(incidents)
# add incidents to map
san_map.add_child(incidents)
以熱力圖的方式呈現
from folium.plugins import HeatMap
san_map = folium.Map(location=[37.77, -122.42], zoom_start=12,width='50%',height='50%')
# Convert data format
heatdata = data[['Y','X']].values.tolist()
# add incidents to map
HeatMap(heatdata).add_to(san_map)
san_map
在地圖上呈現GeoJSON邊界數據
import json
import requests
# url = 'https://cocl.us/sanfran_geojson'
url = 'san-francisco.geojson'
san_geo = f'{url}'
san_map = folium.Map(location=[37.77, -122.42], zoom_start=12,width='50%',height='50%')
folium.GeoJson(
san_geo,
style_function=lambda feature: {
'fillColor': '#ffff00',
'color': 'blue',
'weight': 2,
'dashArray': '5, 5'
}
).add_to(san_map)
san_map
在GeoJSON上繪製Choropleth分級著色圖
# Count crime numbers in each neighborhood
disdata = pd.DataFrame(cdata['PdDistrict'].value_counts())
disdata.reset_index(inplace=True)
disdata.rename(columns={'index':'Neighborhood','PdDistrict':'Count'},inplace=True)
san_map = folium.Map(location=[37.77, -122.42], zoom_start=12,width='50%',height='50%')
folium.Choropleth(
geo_data=san_geo,
data=disdata,
columns=['Neighborhood','Count'],
key_on='feature.properties.DISTRICT',
#fill_color='red',
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
highlight=True,
legend_name='Crime Counts in San Francisco'
).add_to(san_map)
san_map
目前高德的瓦片地址有如下兩種:
前者是高德的新版地址,後者是老版地址。
高德新版的參數:
lang:可以通過zh_cn設置中文,en設置英文
size:基本無作用
scl:瓦片尺寸控制,1=256,2=512
style:設置影像和路網,style=6為衛星圖,style=7為街道圖,style=8為標註圖
ltype:線性控制,增加後,只對地圖要素進行控制,沒有文字註記,要素多少,是否透明
這些規律並不是絕對的,有可能有的組合某些參數不起作用。
谷歌地圖目前谷歌的瓦片地址也存在兩種:
參數詳解:
百度地圖百度當前的瓦片地址:
http://online{0-4}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=202004151&scaler=2&p=0
http://api{0-3}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&udt=20180601&scale=1
http://its.map.baidu.com:8002/traffic/TrafficTileService?level={z}&x={x}&y={y}&time=1373790856265&label=web2D&;v=017
備註:瓦片地址中的x和y對應的並不是經緯度值,而是瓦片編號,中國主要地圖商的瓦片編號流派:
目前百度的瓦片編號比較特殊,Folium暫不支持。
其他參考資料:
https://github.com/geometalab/pyGeoTile
https://github.com/anzhihun/OpenLayers3Primer/blob/master/ch05/05-03.md
http://www.winseliu.com/blog/2018/01/30/map-started-guide/
https://github.com/CntChen/tile-lnglat-transform
騰訊地圖騰訊地圖的瓦片地圖URL格式:
由於騰訊地圖使用的瓦片編碼時TMS,所以使用時需要額外的設置。具體如下:
{0,1,2,3}代表了url的subDomain,在請求時會隨機的在url中使用mt0、mt1、mt2、mt3。{z}代表zoom,即縮放級別,{x}代表列號,{y}代表行號。
GeoQ 官網有公開的多個基於 ArcGIS 的地圖服務,均可使用,詳見https://map.geoq.cn/arcgis/rest/services
4. 參考連結: