地圖視覺化神器folium 上手後直接開大

2021-03-10 12:00:46

一、folium簡介和安裝

1. folium的簡介

  • Folium是建立在 Python 生態系統的資料整理 Datawrangling 能力和 Leaflet.js 庫的對映能力之上的開源庫。用 Python 處理資料,然後用 Folium 將它在 Leaflet 地圖上進行視覺化。Folium能夠將通過 Python 處理後的資料輕鬆地在互動式的 Leaflet 地圖上進行視覺化展示。它不單單可以在地圖上展示資料的分佈圖,還可以使用 Vincent/Vega 在地圖上加以標記。
  • 這個開源庫中有許多來自 OpenStreetMap、MapQuest Open、MapQuestOpen Aerial、Mapbox和 Stamen 的內建地圖元件,而且支援使用 Mapbox 或 Cloudmade 的 API 金鑰來客製化個性化的地圖元件。Folium支援 GeoJSON 和 TopoJSON 兩種檔案格式的疊加,也可以將資料連線到這兩種檔案格式的疊加層,最後可使用 color-brewer 配色方案建立分佈圖。
  • Folium可以讓你用 Python 強大生態系統來處理資料,然後用 Leaflet 地圖來展示。Folium內建一些來自 OpenStreetMap、MapQuest Open、MapQuest Open Aerial、Mapbox和Stamen 的地圖元件(tilesets),並且支援用 Mapbox 或者 Cloudmade API keys 來自定義地圖元件。Folium支援 GeoJSON 和 TopJSON 疊加(overlays),繫結資料來創造一個分級統計圖(Choropleth map)。但是,Folium庫繪製熱點圖的時候,需要聯網才可顯示。

2. 安裝folium

pip install folium -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

二、基本使用

folium 顯示地圖的類為 folium.Map,類的宣告如下:

class 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:經緯度,list 或者 tuple 格式,順序為 latitude,longitude。
  • zoom_start:縮放值,預設為 10,值越大比例尺越小,地圖放大級別越大。
  • control_scale:Bool型,控制是否在地圖上新增比例尺,預設為 False 即不新增。
  • tiles:顯示樣式,預設 「OpenStreetMap」,也就是開啟街道顯示。
  • crs:地理座標參考系統,預設為 「EPSG3857」。

1. 各級別地圖

世界地圖

import folium

print(folium.__version__)

# define the world map
world_map = folium.Map()
# save world map
world_map.save('test_01.html')

結果如下:

當前folium版本:0.11.0

國家地圖

import folium
# define the national map
national_map = folium.Map(location=[35.3, 100.6], zoom_start=4)
# save national map
national_map.save('test_02.html')

結果如下:

市級地圖

其實改變地圖顯示也就是改變顯示的經緯度和縮放比例,省級、市級、縣級用法相似,這裡舉一個市級的例子為例,如北京市:

import folium
# define the national map
city_map = folium.Map(location=[39.93, 116.40], zoom_start=10)
# save national map
city_map.save('test_03.html')

2. 在地圖上標記

普通標記

新增普通標記用 Marker,可以選擇標記的圖案。

# -*- coding: UTF-8 -*-
"""
@File    :folium_map4.py
@Author  :葉庭雲
@CSDN    :https://yetingyun.blog.csdn.net/
"""
import folium

bj_map = folium.Map(location=[39.93, 115.40], zoom_start=12, tiles='Stamen Terrain')

folium.Marker(
    location=[39.95, 115.33],
    popup='Mt. Hood Meadows',
    icon=folium.Icon(icon='cloud')
).add_to(bj_map)

folium.Marker(
    location=[39.96, 115.32],
    popup='Timberline Lodge',
    icon=folium.Icon(color='green')
).add_to(bj_map)

folium.Marker(
    location=[39.93, 115.34],
    popup='Some Other Location',
    icon=folium.Icon(color='red', icon='info-sign')    # 標記顏色  圖示
).add_to(bj_map)

bj_map.save('test_04.html')

結果如下:

圓形標記

新增圓形標記用 Circle 以及 CircleMarker

# -*- coding: UTF-8 -*-
"""
@File    :folium_map5.py
@Author  :葉庭雲
@CSDN    :https://yetingyun.blog.csdn.net/
"""
import folium

bj_map = folium.Map(location=[39.93, 116.40], zoom_start=12, tiles='Stamen Toner')

folium.Circle(
    radius=200,
    location=(39.92, 116.43),
    popup='The Waterfront',
    color='#00FFFF',   # 顏色
    fill=False,        # 填充
).add_to(bj_map)

folium.CircleMarker(
    location=(39.93, 116.38),
    radius=50,   # 圓的半徑
    popup='Laurelhurst Park',
    color='#FF1493',
    fill=True,
    fill_color='#FFD700'
).add_to(bj_map)

bj_map.save('test_05.html')

結果如下:

動態放置標記

import folium

dynamic_tagging = folium.Map(
    location=[46.8527, -121.7649],
    tiles='Stamen Terrain',
    zoom_start=13
)

folium.Marker(
    [46.8354, -121.7325],
    popup='Camp Muir'
).add_to(dynamic_tagging)

dynamic_tagging.add_child(folium.ClickForMarker(popup='Waypoint'))
dynamic_tagging.save('test_06.html')

結果如下:


更多詳細使用可以參考官方檔案:http://python-visualization.github.io/folium/quickstart.html

三、實戰案例

以將停車場地理位置資料視覺化在地圖上範例,熟悉 folium 地圖視覺化的使用。

1. 獲取經緯度資料

停車場地理位置資料來源於網路,資料真實可靠,下面先利用 Python 爬蟲獲取資料

# -*- coding: UTF-8 -*-
"""
@Author  :葉庭雲
@公眾號  : 修煉Python
@CSDN    :https://yetingyun.blog.csdn.net/
@資料來源:http://219.136.133.163:8000/Pages/Commonpage/login.aspx
"""
import requests
import csv
import json
import logging

headers = {
    'X-Requested-With': 'XMLHttpRequest',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
}
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')
url = 'http://219.136.133.163:8000/Pages/Commonpage/AsyGetData.asmx/GetParkList'
s = requests.session()
s.get(url, headers=headers)
for i in range(1, 318):
    data = {
        'cp': str(i),
        'ps': '10',
        'kw': '',
        'lon': 'undefined',
        'lat': 'undefined',
        'type': 'undefined'
    }
    url = 'http://219.136.133.163:8000/Pages/Commonpage/AsyGetData.asmx/GetParkList'
    # post提交表單資料
    res = s.post(url, data=data, headers=headers)
    # 重新設定編碼
    res.encoding = 'utf-8'
    # str轉json  便於提取資料
    result = json.loads(res.text)['Result']
    for j in result:
        park_name = j['ParkName']
        Lon = j['Longitude']
        Lat = j['Latitude']
        with open('parkings.csv', 'a+', newline='', encoding='gb18030') as f:
            f_csv = csv.writer(f)
            f_csv.writerow([park_name, Lon, Lat])
            logging.info([park_name, Lon, Lat])

結果如下:


共有 3170 個停車場地理位置資料

2. folium地圖視覺化

# -*- coding: UTF-8 -*-
"""
@File    :folium_map.py
@Author  :葉庭雲
@CSDN    :https://yetingyun.blog.csdn.net/
"""
import pandas as pd
import folium

# 讀取csv資料
data = pd.read_csv('parkings.csv', encoding='gbk')
# 傳入緯度和經度資料
park_map = folium.Map(location=[data['latitude'].mean(), data['longitude'].mean()], zoom_start=10, control_scale=True,)
# 範例化 folium.map.FeatureGroup 物件
incidents = folium.map.FeatureGroup()
for name,row in data.iterrows():
    incidents.add_child(
        folium.CircleMarker(            # CircleMarker表示花圓
            (row["latitude"], row["longitude"]),   # 每個停車場的經緯度座標
            radius=7,                   # 圓圈半徑
            color='#FF1493',            # 標誌的外圈顏色
            fill=True,                  # 是否填充
            fill_color='#00FF00',       # 填充顏色
            fill_opacity=0.4            # 填充透明度
        )
    )

park_map.add_child(incidents)
park_map.save('park_map1.html')

效果如下:

這樣看起來有點亂,下面我們來統計一下各個局域的停車場數量

import pandas as pd
import folium
from folium import plugins

data = pd.read_csv('parkings.csv', encoding='gbk')
park_map = folium.Map(location=[data['latitude'].mean(), data['longitude'].mean()], zoom_start=10, control_scale=True,)
marker_cluster = plugins.MarkerCluster().add_to(park_map)

for name,row in data.iterrows():
    folium.Marker(location=[row["latitude"], row["longitude"]]).add_to(marker_cluster)
park_map.save('park_map2.html')

效果如下:

這樣能對各個局域停車場的數量在地圖上進行統計,將圖不斷放大以後,還可以顯示每個停車場的具體位置,非常方便。

作者:葉庭雲 公眾號:修煉Python
CSDN:https://yetingyun.blog.csdn.net/
本文僅用於交流學習,未經作者允許,禁止轉載,更勿做其他用途,違者必究。
覺得文章對你有幫助、讓你有所收穫的話,期待你的點贊呀,不足之處,也可以在評論區多多指正。