如何使用folium制作分类choropleth地图为不同类别配置独特色
Folium按分类字段绘制唯一色Choropleth地图实现方案
原生folium.Choropleth接口默认支持数值型字段的梯度着色,你需要按Category分类给每个国家分配唯一区分色的需求,通过自定义样式映射即可实现,不需要额外依赖复杂插件。
核心逻辑:提前建立「分类-唯一色」的映射关系,遍历地理边界要素时,通过ISO_A3编码匹配对应分类的填充色,未匹配到数据的国家默认填充浅灰色
额外优化:补充自定义分类图例,弥补原生接口不支持分类图例的问题
完整可运行代码
import pandas as pd import folium import json from branca.element import MacroElement, Template # 1. 加载/构造你的数据集,提前处理文本转义问题 df = pd.DataFrame([ ["DEU", "Belletristik", 25.9], ["AUT", "Ratgeber", 25.6], ["CHE", "Belletristik", 27.7], ["USA", "Fiction & related items", 11.0], ["PRT", "Mathematics & science", 84.0], ["GBR", "Children's, Teenage & educational", 18.9] ], columns=["ISO_A3", "Category", "Percent"]) # 替换数据里的HTML转义字符,避免显示异常 df["Category"] = df["Category"].str.replace("&", "&") # 2. 为每个唯一分类分配高区分度的固定颜色 unique_categories = df["Category"].drop_duplicates().tolist() # 可自行替换为你需要的色值,数量和分类数保持一致即可 category_colors = ["#e6194B", "#3cb44b", "#ffe119", "#4363d8", "#f58231", "#911eb4"][:len(unique_categories)] cat_to_color = dict(zip(unique_categories, category_colors)) # 提前生成ISO_A3到对应填充色的映射表,渲染时直接查询提升效率 iso_to_color = df.set_index("ISO_A3")["Category"].map(cat_to_color).to_dict() # 3. 初始化folium底图,可自行调整中心点和缩放级别 m = folium.Map(location=[30, 10], zoom_start=3, tiles="OpenStreetMap") # 4. 加载地理边界数据:替换为你本地带ISO_A3编码字段的GeoJSON文件路径 with open("world_iso3.geojson", "r", encoding="utf-8") as f: geo_boundary = json.load(f) # 5. 自定义要素样式规则 def feature_style(feature): # 注意:如果你的GeoJSON里ISO_A3直接存在feature根节点下,把下一行改成 feature.get("ISO_A3", "") iso_code = feature["properties"].get("ISO_A3", "") fill_color = iso_to_color.get(iso_code, "#f5f5f5") return { "fillColor": fill_color, "color": "#333333", "weight": 0.7, "fillOpacity": 0.75 } # 6. 添加着色后的地理图层,可自定义tooltip显示内容 folium.GeoJson( geo_boundary, style_function=feature_style, tooltip=folium.GeoJsonTooltip( fields=["ISO_A3", "name"], aliases=["国家编码:", "国家名称:"], localize=True ) ).add_to(m) # 7. 添加自定义分类图例 legend_template = ''' {% macro html(this, kwargs) %} <div style="position:fixed; left:20px; bottom:20px; z-index:9999; background:#fff; padding:10px 14px; border-radius:6px; box-shadow:0 0 5px rgba(0,0,0,0.25);"> <p style="margin:0 0 8px 0; font-weight:bold;">图书分类</p> {% for cat, color in this.color_map.items() %} <div style="display:flex; align-items:center; margin:4px 0;"> <div style="width:16px; height:16px; background:{{color}}; border:1px solid #444; margin-right:8px;"></div> <span style="font-size:13px;">{{cat}}</span> </div> {% endfor %} </div> {% endmacro %} ''' legend = MacroElement() legend._template = Template(legend_template) legend.color_map = cat_to_color m.get_root().add_child(legend) # 渲染保存为本地HTML文件,在Jupyter环境中可直接输出m查看 m.save("category_map.html")
调整说明
- 如果你的GeoJSON文件里国家编码字段不是
ISO_A3,只需要修改feature_style函数里取编码的字段名,保证和DataFrame里的ISO_A3能匹配上即可 - 分类颜色可以根据需求替换,只要保证每个分类对应唯一色值即可,建议选择区分度高的定性色板,避免相近颜色无法区分
- 如果需要在悬浮提示里展示
Percent数值,只需要先把Percent字段合并到GeoJSON的properties里,再把字段加到GeoJsonTooltip的fields列表中即可
内容的提问来源于stack exchange,提问作者aman jaiswar
相关产品推荐
相关产品推荐

