如何基于GeoJSON数据对Bokeh可视化图表实现动态过滤?
动态过滤完全可行,这里提供两种成熟的实现思路:
方案1:直接操作GeoJSONDataSource(适配你现有代码的最小改动方案)
GeoJSONDataSource的geojson属性本身是响应式的,只要修改该属性值,关联的绘图会自动刷新。你只需要提前备份完整的原始GeoJSON数据,在回调里根据选中值过滤后重新赋值即可。
具体修改步骤:
- 提前保存原始完整的GeoJSON数据
- 改写CustomJS回调逻辑,替换你原来的
tjs代码即可
修改后的核心代码片段:
# 原有代码保留,新增原始数据备份 original_geojson = df.to_json() gs = GeoJSONDataSource(geojson=original_geojson) # 改写回调代码 tjs = ''' const fullGeojson = JSON.parse(fullGeo); const selectedTypes = choice.value; let filteredFeatures; // 无选中或全选时恢复全量数据 if (selectedTypes.length === 0 || selectedTypes.length === max_filter) { filteredFeatures = fullGeojson.features; } else { // 按选中的type过滤要素 filteredFeatures = fullGeojson.features.filter(feature => selectedTypes.includes(feature.properties.type) ); } // 构造新的GeoJSON赋值给数据源 const newGeojson = { type: "FeatureCollection", features: filteredFeatures }; map.geojson = JSON.stringify(newGeojson); ''' cjs = CustomJS(args={'choice':mc, 'map':gs, 'max_filter':len(ops), 'fullGeo': original_geojson}, code=tjs)
这个方案不需要改动你其他的绘图逻辑,替换回调部分即可直接运行。
方案2:转用ColumnDataSource使用CDSView过滤
如果你希望用更灵活的CDSView+CustomJSFilter体系,可以直接把GeoDataFrame转为ColumnDataSource,GeoPandas会自动把geometry拆解为xs和ys列适配Bokeh的patches方法:
from bokeh.models import ColumnDataSource, CDSView, CustomJSFilter # 直接把GeoDataFrame转为ColumnDataSource cds = ColumnDataSource(df) # 构造过滤规则 custom_filter = CustomJSFilter(args=dict(choice=mc), code=''' const selectedTypes = choice.value; if (selectedTypes.length === 0) return true; return selectedTypes.includes(source.data['type'][index]); ''') view = CDSView(source=cds, filters=[custom_filter]) # 绘图时指定view参数 plot_area = f.patches('xs', 'ys', source=cds, view=view, line_color=None, line_width=0.25, fill_alpha=1, fill_color='blue') # MultiChoice值变化时触发视图更新 mc.js_on_change('value', CustomJS(args=dict(view=view), code=''' view.filters = [...view.filters] '''))
该方案的优势是可以叠加多个过滤规则,不需要修改原始数据源内容,适合复杂过滤场景。
内容的提问来源于stack exchange,提问作者manoelpqueiroz
相关产品推荐
相关产品推荐

