Folium是一套Python上的地圖視覺化工具。透過Leaflet這個JavaScript Library以及OpenStreetMap地圖服務,可在Jupyter Notebook上實現互動式地圖繪製。本篇將簡單介紹Folium的使用方式以及繪製效果。

OpenStreetMap是由Steve Coast所創立的一個開放地圖協助計畫(類似維基百科),標榜自由且開源的地圖資訊,使用者均可自由使用與加入新內容,目前全球總共有四百多萬名用戶參與OpenStreetMap計畫。

安裝Folium

本篇文章範例均透過Jupyter Notebook實作,因此建議先安裝相關套件並開啟Notebook直接在瀏覽器上操作較為方便。

# 使用pip3安裝Jupyter
pip3 install --upgrade pip
pip3 install jupyter

安裝完成後輸入jupyter notebook在瀏覽器上開啟操作介面。接著安裝Folium套件

pip3 install folium # 安裝 Folium package

更詳細安裝方式可參考官方網站

以下範例基於Folium 0.5.0,後續若有更新可能使用法會有不同。

顯示地圖

在Jupyter Notebook中輸入以下程式碼並執行

import folium # 匯入 folium 套件

# 建立地圖與設定位置
fmap = folium.Map(location=[35.709635, 139.810851], zoom_start=16)
fmap  # 在notebook中顯示地圖

即可直接在Jupyter Notebook顯示地圖資訊。其中location=[35.709635, 139.810851]表示中心經緯度位置,zoom_start=16代表畫面細節為16

map-osm Folium顯示的地圖範例

Folium預設使用OpenStreetMap,此外也可以使用如StamenMapbox等地圖服務(Mapbox須申請並匯入API key)。

map-stamen-toner 使用 Stamen Toner 圖層

map-stamen-terrain 使用 Stamen Terrain 圖層

匯出HTML檔案

Folium也可將繪製好的地圖匯出成HTML檔案,並直接使用瀏覽器開啟觀看結果。

fmap.save('map.html')

執行後會在Python檔案所在資料夾建立一個名為map.html的檔案,可直接用瀏覽器開啟觀看結果。

加入Marker標記

將Marker套用在地圖上,並點擊後顯示popup參數所設定的文字。

fmap = folium.Map(location=[35.709635, 139.810851], zoom_start=17)

fmap.add_child(folium.Marker(location=[35.709635, 139.810851],
                             popup='Skytree'))

map-marker

此外也可設定各個Marker的顏色,屬性與Icon類型

fmap = folium.Map(location=[35.712326, 139.804037],
                  zoom_start=15)

m1 = folium.Marker(location=[35.709635, 139.810851],
                   popup='<b>Skytree</b>')

m2 = folium.Marker(location=[35.707595, 139.795530],
                   popup='<i>Hotel</i>',
                   icon=folium.Icon(icon='bed', # Icon類型
                                    color='green', # Marker顏色
                                    prefix='fa')) # 使用Font Awesome Icons

m3 = folium.Marker(location=[35.715092, 139.796666],
                   popup='Asakusa Temple',
                   icon=folium.Icon(icon='info-sign',
                                    color='red'))
# 將各Marker加入地圖。
fmap.add_child(child=m1)
fmap.add_child(child=m2)
fmap.add_child(child=m3)

map-markers

Circle 圖示

若要加入圓形標記,可使用folium.Circle物件

center_pos = [35.709635, 139.810851]
fmap = folium.Map(location=center_pos, zoom_start=17)
fmap.add_child(folium.Circle(location=center_pos,
                             color='green', # Circle 顏色
                             radius=30, # Circle 寬度
                             popup='Skytree', # 彈出視窗內容
                             fill=True, # 填滿中間區域
                             fill_opacity=0.5 # 設定透明度
                             ))

map-markers

繪製線條

要使用Folium繪製地圖線條,可使用提供PolyLine這個函數,並可設定線條顏色,寬度,透明度等屬性。

points = [[35.709635, 139.810851],
          [35.707595, 139.795530],
          [35.715092, 139.796666]]

fmap.add_child(folium.PolyLine(locations=points, # 座標List
                               weight=8)) # 線條寬度

map-poly-lines

HeatMap(熱度圖)

若要在Folium繪製熱度圖,可使用folium.plugins中的HeatMap物件

import numpy as np
from folium.plugins import HeatMap

fmap = folium.Map(location=[35.712326, 139.804037], zoom_start=12)

# 建立隨機資料
data = (np.random.normal(size=(100, 3)) * 0.02 *
        np.array([[1, 1, 1]]) +
        np.array([[35.712326, 139.804037, 1]])).tolist()

fmap.add_child(HeatMap(data=data))

map-heatmap

除了單張熱度圖外,也可以使用HeatMapWithTime元件來顯示連續的時間軸。

import numpy as np
from folium.plugins import HeatMapWithTime

center_pos = [35.712326, 139.804037]

# 使用 numpy 建立初始資料
initial_data = (np.random.normal(size=(200, 2)) *
                np.array([[0.02, 0.02]]) +
                np.array([center_pos]))

# 建立連續資料
data = [initial_data.tolist()]
for i in range(20):
    data.append((data[i] + np.random.normal(size=(200, 2)) * 0.001).tolist())

fmap = folium.Map(center_pos, zoom_start=11)
fmap.add_child(HeatMapWithTime(data)) # 顯示連續熱度圖

map-heatmap-time-1 第 1 筆資料的熱度圖

map-heatmap-time-11 第 11 筆資料的熱度圖

可使用內部元件控制要顯示的資料筆數,以及執行連續往前或往後播放資料等功能。

GeoJson 與 TopoJson 匯入

Folium也提供GeoJson以及TopJson檔案的匯入並繪圖的功能。下面展示使用GeoJson繪製澳洲地圖的範例,相關檔案可由Github下載GeoJson檔案,並放入與Python檔案相同的資料夾中。

GeoJson是一種開放地圖繪製標準,可透過Json格式的文件在地圖上繪製所想要的點,線,面積等效果。TopoJson則是GeoJson的擴展,可繪製更複雜的地圖效果。

fmap = folium.Map(
    location=[-24.908886, 132.388750],
    zoom_start=4)

fmap.add_child(folium.GeoJson('AUS.geo.json', name='geojson')) # 使用"AUS.geo.json"檔案來繪製地圖

map-geojson Australia 地圖輪廓

Reference