iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 10
0

folium是基於leaflet.js的python地圖套件,讓使用者可以很快速的使用python產生一些可互動的地圖。
我們可以很方便把加工後的GIS資料丟進去,並完成一個網頁地圖。

leaflet: [Day 13] WebGIS中的向量資料-在Leaflet實作 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天

以下我們就快速來試一試
大綱:

  • 基本操作
  • 加入向量資料
  • 時序地圖

基本操作

安裝 folium
conda install -c conda-forge folium

初始化地圖
初始化地圖要指定地圖中心的經緯度坐標,跟比例尺(zomm_start)
例如:

import folium
m = folium.Map((25.0133904,121.52245),zoom_start=14)
m

https://ithelp.ithome.com.tw/upload/images/20181025/20107816JJuymkhfJt.png

folium內建一些基本的WMTS,使用tiles,我們把它換成使用Cartodb Positron

m = folium.Map((25.0133904,121.52245), tiles="Cartodb Positron",zoom_start=14)
m

https://ithelp.ithome.com.tw/upload/images/20181025/201078160s7ArzQK5C.png

當然,還有很多其他選擇,有需要的人可以自行參考

加入向量資料

folium的操作沒有很複雜,如果要加入向量資料,操作起來跟leaflet很像。

例如我們增加一個marker然後設定style及popup

m = folium.Map((25.0133904,121.52245),zoom_start=14)
folium.CircleMarker(
    location=[25.0133904,121.52245],
    radius=20,
    popup='永和',
    color='#3186cc',
    fill=True,
    fill_color='#3186cc'
).add_to(m)
m

https://ithelp.ithome.com.tw/upload/images/20181025/20107816fEhqTioBMW.png

若要丟整份資料,folium使用的格式是geojson,如果是Geopandas處理的資料,可以使用to_json()這個方法將資料餵進去。

再次以新北的村里界資料為範例
先把資料準備好並轉好坐標系統為epsg4326

import geopandas as gpd
village=gpd.read_file('data/village/village.shp',encoding='utf-8')
village=village[village.is_valid]
village=village[village['ADMIT']=='永和區']
village.crs = {'init' :'epsg:3826'} # 避免資料沒設,這邊再重新給一次
village=village.to_crs(epsg=4326)
village=village.reset_index()

處理好的資料是GeoDataFrame丟進去,可以用to_json轉為geojson
並直接丟進去folium

m = folium.Map((25.0133904,121.52245),zoom_start=14)
folium.GeoJson(
    village.to_json(),
    name='geojson'
).add_to(m)
m

https://ithelp.ithome.com.tw/upload/images/20181025/20107816HG0BOrqSk6.png

如果要增加圖層開關,讓瀏覽的時候比較方便,可以加入LayerControl(用法跟leaflet差不多)

folium.LayerControl().add_to(m)

https://ithelp.ithome.com.tw/upload/images/20181025/20107816vvcy7RYzNX.png

時序地圖

folium有一個滿好用的套件TimeSliderChoropleth
可以快速做一個時間序列的資料展示
他的基本操作如下:

g = TimeSliderChoropleth(
    village.to_json(),
    styledict = styledict,  
).add_to(m)

其中,styledict定義的是時序資料的值
餵進去的資料需要按照要求
為了演示,我們針對village隨機產生時序資料

import pandas as pd
import numpy as np
n_periods = 24
n_sample = 12
assert n_sample < n_periods
dt_index = pd.date_range('2012-1-1', periods = n_periods, freq='M').strftime('%s')
styledata = { }

for item in village.index: 
    df = pd.DataFrame({'color': np.random.normal(size=n_periods), 
                       'opacity': np.random.normal(size=n_periods)},
                      index = dt_index)
    df = df.cumsum()
    df.sample(n_sample, replace=False).sort_index()
    styledata[item] = df

styledict = {str(country): data.to_dict(orient='index') for 
             country, data in styledata.items()}
            

產生的資料結構是長這樣
https://ithelp.ithome.com.tw/upload/images/20181025/20107816epB85W0rAc.png

我們把向量圖丟進去,
並把上面產生的styledict也放進去

from folium.plugins import TimeSliderChoropleth
m = folium.Map((25.0133904,121.52245), tiles="Cartodb Positron",zoom_start=14)
g = TimeSliderChoropleth(
    village.to_json(),
    styledict = styledict,
    
).add_to(m)

m

https://ithelp.ithome.com.tw/upload/images/20181025/201078164mrDypE8Q3.png

後記

folium還很很多功能,可以講個好幾天,之後幾天有機會再多看看吧!

參考資料
folium

今天的練習請參考github


上一篇
Day09 使用GeoPlot
下一篇
Day11 台鐵意外事件與folium練習-前處理
系列文
30天精通GIS資料分析-使用Python30

尚未有邦友留言

立即登入留言