You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bokeh滑块组件无法更新地理地图绘图问题求助

问题原因和修正方案

核心错误点

    1. update_map回调函数中调用plot_area生成了新的绘图对象,但没有将新对象替换到已挂载的布局中,原有页面上的绘图实例完全没有被修改,自然不会有更新效果。
    1. get_dataset函数存在参数名笔误:形参声明为dataframe,但函数内部调用时用的是未定义的geodataframe变量,会直接抛出变量不存在的错误。
    1. 绘图逻辑设计不合理:每次触发更新都重新创建整个绘图实例、瓦片图层、颜色条等组件,不仅效率极低,也不符合Bokeh Server的更新逻辑——正确做法是复用已有的绘图实例,仅更新数据源的内容。
    1. plot_area函数内部写了导入语句,虽然不直接导致报错,但不符合Python编码规范,也会影响运行效率。

修正步骤

1. 修正get_dataset函数

def get_dataset(dataframe, column, geometry_column, val):
    # 把函数内的geodataframe改成参数名dataframe
    g = dataframe[dataframe[column] == val]
    g_gdf = gpd.GeoDataFrame(g, geometry=geometry_column)
    g_gdf.crs = 'EPSG:3857'
    return g_gdf

2. 重构绘图逻辑,抽离可复用组件

不要每次更新都重建整个图,我们把数据源、绘图实例、patch渲染器都抽出来复用:

# 所有导入统一放到文件顶部
from bokeh.plotting import figure
from bokeh.tile_providers import get_provider
from bokeh.models import GeoJSONDataSource, ColorBar, BasicTicker, LinearColorMapper
from bokeh.models.widgets import Slider, Paragraph
from bokeh.layouts import row, widgetbox
from bokeh.io import curdoc
import geopandas as gpd

# 先计算全局颜色映射范围,避免每次更新颜色条范围变化
global_min = precipitacao_por_bacia['val'].min()
global_max = precipitacao_por_bacia['val'].max()

# 初始化数据源
initial_g = get_dataset(precipitacao_por_bacia,'datahora','st_astext',dias[0])
initial_g.reset_index(drop=True,inplace=True)
initial_g['datahora'] = initial_g['datahora'].apply(lambda x: str(x))
poligonos_ds = GeoJSONDataSource(geojson=initial_g.to_json())

# 初始化绘图实例,仅创建一次
tile_provider = get_provider('CARTODBPOSITRON_RETINA')
p = figure(title='Precipitação ', plot_width=500, plot_height=500, tooltips=[('Bacia','@bacia_nome'), ('precipitação','@val')])
p.add_tile(tile_provider)
p.axis.visible = False

# 添加颜色映射和图层,仅创建一次
color_mapper = LinearColorMapper(palette='Viridis256', low=global_min, high=global_max)
color_bar = ColorBar(color_mapper=color_mapper, ticker=BasicTicker(), location=(0,0), label_standoff=12)
p.patches('xs','ys', source=poligonos_ds, fill_alpha=1, line_width=0.5, line_color='black', fill_color={'field' :'val', 'transform': color_mapper})
p.add_layout(color_bar, 'left')

# 重写update回调,仅更新数据源
def update_map(attrname, old, new):
    g = get_dataset(precipitacao_por_bacia,'datahora','st_astext',dias[slider.value])
    g.reset_index(drop=True,inplace=True)
    g['datahora'] = g['datahora'].apply(lambda x: str(x))
    # 直接更新数据源的geojson属性即可触发绘图更新
    poligonos_ds.geojson = g.to_json()
    output.text = str(g['datahora'][0])

# 控件和布局逻辑保持不变
slider = Slider(title="Day", value=0, start=0, end=409)
output = Paragraph()
slider.on_change('value', update_map)
layout = row(p, widgetbox(slider, output))
curdoc().add_root(layout)

补充说明

如果你的应用需要根据过滤后的数据动态调整颜色条范围,可以在update回调中同步修改color_mapper.low和color_mapper.high属性即可。

内容的提问来源于stack exchange,提问作者Gabriel Lima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 12:18:01