Python如何使用bokeh包和geojson數據繪制地圖
最近要繪制倫敦區地圖,查閱了很多資料后最終選擇使用bokeh包以及倫敦區的geojson數據繪制。bokeh是基于python的繪圖工具,可以繪制各種類型的圖表,支持geojson數據的讀取及繪制地圖。
安裝bokeh
$ pip install bokeh
軟件版本
python-3.7.7bokeh-2.0.0
數據來源
倫敦地圖數據來源于Highmaps地圖數據集。下載的是英國的地圖數據united-kindom.geo.json。需要對得到的數據進行預處理才能得到只含倫敦地區的數據。這需要對geojson數據的格式有一定的了解。在對數據進行處理之前,先看如何繪制英國地圖。
繪制英國地圖
from bokeh.plotting import curdoc, figurefrom bokeh.models import GeoJSONDataSource# 讀入英國地圖數據并傳給GeoJSONDataSourcewith open('united-kindom.geo.json', encoding='utf8') as f: geo_source = GeoJSONDataSource(geojson=f.read())# 設置一張畫布p = figure(width=500, height=500)# 使用patches函數以及geo_source繪制地圖p.patches(xs=’xs’, ys=’ys’, source=geo_source)curdoc().add_root(p)
上述代碼可以繪制出英國地圖。將上述代碼保存為test.py,在終端運行
$ bokeh serve --show test.py
這會自動打開瀏覽器,并顯示英國地圖。運行結果如圖:
獲取倫敦地區數據
獲取倫敦地區數據可以手動從united-kingdom.geo.json文件中篩選出倫敦的數據,也可以先用python先把數據過濾一遍,然后將數據傳給bokeh。這需要對geojson文件格式有一定的了解,在此不詳細介紹。
from bokeh.plotting import curdoc, figurefrom bokeh.models import GeoJSONDataSourceimport json# 用json庫讀取數據with open('united-kindom.geo.json', encoding='utf8') as f: data = json.loads(f.read())# 判斷是不是倫敦地區數據def isInLondon(district): if ’type’ in district[’properties’] and ’london borough’ in district[’properties’][’type’].lower(): return True if ’type-en’ in district[’properties’] and ’london borough’ in district[’properties’][’type’].lower(): return True if ’woe-name’ in district[’properties’] and ’city of london’ in district[’properties’][’woe-name’].lower(): return True return False# 過濾數據data[’features’] = list(filter(isInLondon, data[’features’]))#geo_source = GeoJSONDataSource(geojson=json.dumps(data))p = figure(width=500, height=500)p.patches(xs=’xs’, ys=’ys’, source=geo_source)curdoc().add_root(p)
運行結果如圖:
美化
上面的倫敦地圖只是一個大概的輪廓,下面對地圖添加一系列功能。
添加各區輪廓線
p.patches(xs=’xs’, ys=’ys’, fill_alpha=0.7, # 畫輪廓線 line_color=’white’, # 線的顏色 line_width=0.5, # 線的寬度 source=geo_source)
現在地圖區域輪廓很清晰。
添加顏色
# 為每一個地區增加一個color屬性for i in range(len(data[’features’])): data[’features’][i][’properties’][’color’] = [’blue’, ’red’, ’yellow’, ’orange’, ’gray’, ’purple’][i % 6]p.patches(xs=’xs’, ys=’ys’, fill_alpha=0.7, line_color=’white’, line_width=0.5, color='color', # 增加顏色屬性,這里的'color'對應每個地區的color屬性 source=geo_source)
現在地圖五顏六色。
增加圖注
import random# 隨機產生數據用于展示for i in range(len(data[’features’])): data[’features’][i][’properties’][’number’] = random.randint(0, 20_000)p = figure(width=500, height=500, tooltips='@name, number: @number' # 使用tooltips生成圖注,@+屬性名稱,這里的name是數據中原本有的,number是新近添加的。 )
現在鼠標放到區域上時,會顯示'區域名, number: 數字'。
去掉坐標軸與背景線
p.axis.axis_label = Nonep.axis.visible = Falsep.grid.grid_line_color = None
最終代碼
from bokeh.plotting import curdoc, figurefrom bokeh.models import GeoJSONDataSourceimport jsonimport randomwith open('united-kindom.geo.json', encoding='utf8') as f: data = json.loads(f.read())def isInLondon(district): if ’type’ in district[’properties’] and ’london borough’ in district[’properties’][’type’].lower(): return True if ’type-en’ in district[’properties’] and ’london borough’ in district[’properties’][’type’].lower(): return True if ’woe-name’ in district[’properties’] and ’city of london’ in district[’properties’][’woe-name’].lower(): return True return Falsedata[’features’] = list(filter(isInLondon, data[’features’]))for i in range(len(data[’features’])): data[’features’][i][’properties’][’color’] = [’blue’, ’red’, ’yellow’, ’orange’, ’gray’, ’purple’][i % 6] data[’features’][i][’properties’][’number’] = random.randint(0, 20_000)geo_source = GeoJSONDataSource(geojson=json.dumps(data))p = figure(width=500, height=500, tooltips='@name, number: @number')p.patches(xs=’xs’, ys=’ys’, fill_alpha=0.7, line_color=’white’, line_width=0.5, color='color', source=geo_source)p.axis.axis_label = Nonep.axis.visible = Falsep.grid.grid_line_color = Nonecurdoc().add_root(p)
倫敦地圖完成了
總結
最開始想用pyecharts做的,但是pyecharts并沒有倫敦的地圖。折騰半天,最后只好自己找geojson數據來畫地圖。
找到了很多關于地圖的數據和工具,比如上文中提到的highmap數據集,以及DataV.altas,這個工具可以可視化地提取中國區域的地圖數據,但感覺比起自己找數據,畫中國地圖還是pyecharts來得實在。
數據最重要。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。
相關文章: