如何用gv.Polygons替代gv.Shape绘制英国行政区划Choropleth地图
解决方案:Geoviews绘制LAD19联动地图(两种路径)
看起来你卡在Geoviews几何对象维度错误和联动功能实现上了,我之前处理英国行政区数据时也踩过类似的坑,给你两个可行的解决方案:
路径一:修复gv.Polygons的DataError并实现联动
你的DataError几乎可以肯定是GeoDataFrame里的几何对象带了三维Z坐标——OSGB(27700)的LAD19 shp文件经常会附带不必要的Z维度,而gv.Polygons只支持二维平面几何。按以下步骤修复:
1. 先把几何转成二维
用GeoPandas的to_2d()方法直接移除Z坐标:
import geopandas as gpd import geoviews as gv import pandas as pd import hvplot.pandas # 加载并预处理数据 gdf = gpd.read_file("LAD19_shapefile.shp") # 检查是否有Z坐标(可选) print(gdf.geometry.has_z.unique()) # 转换为二维几何 gdf["geometry"] = gdf["geometry"].to_2d() # 合并人口数据(确保用唯一关联键,比如LAD19CD) population_df = pd.read_csv("population_data.csv") merged_gdf = gdf.merge(population_df, on="LAD19CD", how="left").dropna(subset=["population"])
2. 正确初始化gv.Polygons并绑定联动
指定唯一标识的kdims(行政区代码)和着色用的vdims(人口数),再绑定点击事件到右侧表格:
# 创建Polygons交互式图层 lad_polygons = gv.Polygons(merged_gdf, kdims=["LAD19CD"], vdims=["population", "LAD19NM"]).opts( tools=["tap", "hover"], color="population", cmap="viridis", colorbar=True, width=800, height=600, title="英国LAD19行政区人口分布" ) # 定义联动表格生成函数 from bokeh.models.widgets import DataTable, TableColumn def render_selected_table(selected_data): if not selected_data: return DataTable(columns=[], data=[]) # 获取选中的行政区数据 selected_cd = selected_data["LAD19CD"][0] selected_row = merged_gdf[merged_gdf["LAD19CD"] == selected_cd].to_dict("records")[0] # 定义表格列 columns = [ TableColumn(field="LAD19NM", title="行政区名称"), TableColumn(field="population", title="人口数"), TableColumn(field="LAD19CD", title="行政区代码") ] return DataTable(columns=columns, data=[selected_row]) # 绑定点击事件到表格 linked_table = hvplot.bind(render_selected_table, lad_polygons.data).widgets() # 组合地图和表格显示 lad_polygons + linked_table
路径二:直接实现gv.Shape的联动功能
如果不想切换到gv.Polygons,gv.Shape完全可以实现联动,核心是利用Holoviews的Selection1D流来绑定选择事件:
1. 初始化gv.Shape图层
同样先确保几何是二维,然后启用交互工具:
import holoviews as hv hv.extension("bokeh") # 复用之前预处理好的merged_gdf lad_shape = gv.Shape(merged_gdf, kdims=["LAD19CD"], vdims=["population", "LAD19NM"]).opts( tools=["tap", "hover"], color="population", cmap="viridis", width=800, height=600 )
2. 绑定选择事件到图表/表格
比如绑定到一个柱状图,显示选中行政区的人口数据:
# 定义联动更新函数 def update_chart(selected_indices): if not selected_indices: return hv.Bars([]).opts(title="请选择一个行政区") # 获取选中行的行政区代码 selected_cd = merged_gdf.iloc[selected_indices]["LAD19CD"].iloc[0] selected_data = merged_gdf[merged_gdf["LAD19CD"] == selected_cd] # 返回柱状图(可以扩展为对比多个数据,比如和全国平均) return hv.Bars(selected_data, kdims="LAD19NM", vdims="population").opts( width=400, height=300, title="选中行政区人口" ) # 绑定选择流:tap事件触发更新 linked_chart = hv.DynamicMap(update_chart, streams=[hv.streams.Selection1D(source=lad_shape)]) # 组合地图和图表 lad_shape + linked_chart
关键注意事项
- 无论哪种方法,必须确保几何是二维:用
gdf.geometry.has_z检查,有Z值就用to_2d()转换 - 联动的核心是
kdims必须是唯一标识列(比如LAD19CD),这样选中事件才能精准关联数据 - 合并数据后记得清理空值:用
dropna(subset=["population"])避免渲染错误
内容的提问来源于stack exchange,提问作者mmTmmR
相关产品推荐
相关产品推荐

