上一篇Folium的文章中,针对Choropleth的使用有过简单的介绍,但是对于如何调整分级样式图等,没有进一步的阐述。这篇文章结果自己的使用经验做些简单的总结。
生成Choropleth分级着色图的方法目前主要有两种,一种是使用folium.Choropleth(),另外一种是使用folium.GeoJson()。接下来详细讲解两种方式的不同。
folium.Choropleth()
这个类可以将GeoJSON的图形覆盖到地图上。如果不绑定数据则显示单色的地图,如果绑定数据则通过值得大小显示不同颜色。具体使用方法:
class folium.features.Choropleth(geo_data, data=None, columns=None, key_on=None, bins=6, fill_color=None, nan_fill_color='black', fill_opacity=0.6, nan_fill_opacity=None, line_color='black', line_weight=1, line_opacity=1, name=None, legend_name='', overlay=True, control=True, show=True, topojson=None, smooth_factor=None, highlight=None, **kwargs)
参数说明:
- geo_data:指定GeoJSON,可以是JsonURL、file path或其他类型 (json、dict、geopandas等)的GeoJSON几何数据
- data:需要绑定的GeoJSON的数据,默认为空。传入的数据可以是Pandas DataFrame或Series,具体Series没有使用过,拆测如果传Series需要将index设置为匹配项。
- columns:当数据传入的时Pandas DataFrame设定想要的值,第一列需要与GeoJSON匹配的列,第二列为具体的值
- key_on:GeoJSON中需要绑定的列,默认为空。格式中需要以feature对象开头,如id或 feature.properties.statename
- bins:设定对值要划分的数量,默认为6,如果传入的是数值,则传入数字时,会使用data中的最大值和最小值进行平均划分。如果传入的是一个序列,则会按序列定义边界。同时也可以传入字符串,可传入的字符串可以从histogram的文档中找到。
- fill_color:区域需要填充的颜色,默认为blue,可以传入16进制的颜色代码或颜色名称,如果绑定了数据,则可以传入“颜色地图”,比如:‘BuGn’, ‘BuPu’, ‘GnBu’, ‘OrRd’, ‘PuBu’, ‘PuBuGn’, ‘PuRd’, ‘RdPu’, ‘YlGn’, ‘YlGnBu’, ‘YlOrBr’, and ‘YlOrRd’.
- nan_fill_color:NaN区域填充的颜色,默认为’black’,即GeoJSON中没有匹配到的图形填充的颜色。
- fill_opacity :填充颜色的透明度,默认为6,可选值为0-1
- nan_fill_opacity:NaN区域填充颜色透明度,默认取fill_opacity的值。
- line_color:区域边框颜色,默认为’black’
- line_weight:区域边框款对,默认为1
- line_opacity:区域边框透明度,默认为1
- legend_name:图例标识名称
- topojson:除了GeoJson外,同时也支持TopoJSON格式的的边界数据。 (string, default None) – If using a TopoJSON, passing “objects.yourfeature” to the topojson keyword argument will enable conversion to GeoJSON. TopoJSONs can be passed as “geo_data”, but the “topojson” keyword must also be passed with the reference to the topojson objects to convert. See the topojson.feature method in the TopoJSON API reference: https://github.com/topojson/topojson/wiki/API-Reference
- smooth_factor:平滑因子,主要为了简化每个缩放级别的折线。数值越大表示越平滑,同时性能也更好,数值越小说明越精确,Leaflet中的默认值为0
- highlight:当鼠标悬停在区域上时是否要突出显示,默认为False
- name:层的名字,可选。如果设置了可以在LayerControls中出现。
- overlay:添加层的设置,默认为True(覆盖层),如果传False则为基础层。
- control:是否将图层包含到LayerControls中,默认为True
- show:是否在地图打开时就显示层,默认为True
示例代码:
import folium import pandas as pd geo_json_data = "data/china_city.json" df = pd.read_excel("data/orders.xlsx") m = folium.Map(location=[32, 120], zoom_start=5) folium.Choropleth( geo_data=geo_json_data, data=df, columns=["cityname", "order_count"], key_on="feature.properties.name", fill_color="BuPu", fill_opacity=0.7, line_opacity=0.2, legend_name="Order Count", ).add_to(m)
中间折腾的过程(个人实践):
1、生成城市级别的GeoJSON文件
国内的GeoJSON数据时我从阿里的DataV.GeoAtlas上抓取下来的,国家文件内包含了省份,省份文件下包含了城市。如果要在国家下直接包含城市,则需要自己处理数据:
import json import glob file_path = r'geojson_city\*.json' file_list = glob.glob(file_path) features = [] for file_name in file_list: with open(file_name, 'r') as f: data = json.load(f) for feature in data['features']: features.append(feature) china = {'type': 'FeatureCollection', 'features': features} with open('china_city.json', 'w') as fp: json.dump(china, fp)
2、城市名称的匹配
在使用过程中遇到的第二个问题是,公司数据库中的城市名称与GeoJSON中的城市名是不匹配的,有些带“市”,有些“不带”。另外还包含县级市即直辖市等问题。解决方案是人工进行匹配。具体以GeoJSON中的城市名为准:
with open('china_city.json', 'r') as f: data = json.load(f) for feature in data['features']: print(feature['properties']['name'])
3、对GeoJSON中的区域边界数据进行简化
默认情况下,从阿里抓取过来的GeoJSON的精度非常的的细,实际使用过程中造成绘制图形时非常的慢,且实际使用时并不需要这么详细。解决方案:使用https://mapshaper.org/ 进行抽稀。如下图将18994个线段抽稀到5%(1318个线段)视觉上没有什么区别。
4、填充颜色的选择
文档说颜色是由color brewer(http://colorbrewer2.org/ )顺序调色板生成的。 默认情况下,在值的最小值和最大值之间使用线性划分。
正确传达信息的一个关键点是为您的设计选择一个合适的配色方案。 配色方案主要有三种类型: (1)顺序配色,(2)发散配色,(3)定性配色。
- 顺序的颜色方案按照从低到高的逻辑顺序排列,非常适合表示不包含临界中点或有序类别数据(低/中/高)的数值数据
- 发散的颜色方案突出显示高于或低于一个有趣的中点值(例如平均值)的值。 发散格式用于可以有意义地用中点进行划分的数据
- 定性配色方案用于名义范畴数据(即数据没有固有的顺序)。 类别之间的差异以不同的色调表现出来,明度和饱和度是相似的
ColorBrewer提供的Color Groups:
- sequential
- multihue
- YlGn
- YlGnBu
- GnBu
- BuGn
- PuBuGn
- PuBu
- BuPu
- RdPu
- PuRd
- OrRd
- YlOrRd
- YlOrBr
- singlehue
- Purples
- Blues
- Greens
- Oranges
- Reds
- Greys
- diverging
- PuOr
- BrBG
- PRGn
- PiYG
- RdBu
- RdGy
- RdYlBu
- Spectral
- RdYlGn
- qualitative
- Pastel1
- Pastel2
- Dark2
- Accent
- Paired
- Set1
- Set2
- Set3
- multihue
具体颜色代表的如下:
folium.GeoJson()
folium.GeoJson()类相对来所较为底层,可以在定义更多的样式,但操作更麻烦些。
class folium.features.GeoJson(data, style_function=None, highlight_function=None, name=None, overlay=True, control=True, show=True, smooth_factor=None, tooltip=None, embed=True, popup=None)
参数说明:
- data:GeoJSON数据
- style_function:样式函数
- highlight_function:高亮函数
- name:层的名称
- overlay:同上
- control:同上
- show:同上
- smooth_factor:同上
- tooltip:在地图上显示tooltip,更多详情可以看GeoJsonTooltip
- embed:是否将数据嵌入到html文件中,默认为True
使用示例:
import json import folium import pandas as pd from branca.colormap import linear with open("china_city.json") as f: geo_json_data = json.load(f) df = pd.read_excel("data/orders.xlsx") colormap = linear.RdYlGn_09.scale(df["order_number"].min(), df["order_number"].max()) incr_dict = df.set_index("cityname")["order_number"] m = folium.Map(location=[32, 120], zoom_start=5) folium.GeoJson( geo_json_data, style_function=lambda feature: { "fillColor": colormap(incr_dict.get(feature["properties"]["name"], 0)), "color": colormap(incr_dict.get(feature["properties"]["name"], 0)), "weight": 2, "fill_opacity": 0.7, "line_opacity": 0.2, }, ).add_to(m)
参考链接:
- https://github.com/python-visualization/folium/blob/master/examples/GeoJSON_and_choropleth.ipynb
- https://python-visualization.github.io/folium/modules.html
- https://github.com/python-visualization/folium/blob/master/examples/Colormaps.ipynb
- https://nbviewer.jupyter.org/github/python-visualization/folium/blob/v0.2.0/examples/Colormaps.ipynb
你好,请问下使用folium.Choropleth 办法能做到类似folium.GeoJson 中 tooltip 的功能吗