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

Bokeh下拉菜单选择城市后图表不更新问题求助

Hey there! Let's dig into why your dropdown menu isn't updating the chart. This is a super common gotcha when starting out with Bokeh's interactive features, so let's break it down step by step.

1. First, Check How You're Updating the Data Source

The #1 reason dropdowns fail to update charts is that developers often create a new ColumnDataSource instead of modifying the existing one. Bokeh charts bind to a specific source instance—if you replace it entirely, the chart won't recognize the new data.

Wrong approach:

# Don't do this in your callback!
source = ColumnDataSource(new_city_data)

Correct approach:
Update the data property of your existing source:

# This tells the chart to refresh with new values
source.data = new_city_data

2. Pick the Right Callback Type for Your Use Case

Your choice of callback depends on whether you're using Bokeh Server or a static (browser-only) plot:

Option A: Static Plot with CustomJS (No Server)

If you're not running Bokeh Server, you need to load all city data upfront (since browsers can't read local HDF files directly). Pass all your test data to the CustomJS callback, then swap out the source data when the dropdown changes:

from bokeh.models import Select, CustomJS, ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.layouts import column

# Test data matching your expected structure
city_data = {
    "Beijing": {"days": list(range(1,13)), "sun_hours": [6.2,7.3,9.1,11.2,13.5,14.7,14.1,12.8,10.5,8.3,6.5,5.8]},
    "Shanghai": {"days": list(range(1,13)), "sun_hours": [5.8,6.7,8.2,10.1,12.3,13.5,12.9,11.7,9.8,7.6,6.1,5.5]},
    "Guangzhou": {"days": list(range(1,13)), "sun_hours": [4.5,5.2,6.8,8.5,10.2,11.3,10.8,9.7,8.3,6.9,5.7,4.9]}
}

# Initialize with default city data
source = ColumnDataSource(data=city_data["Beijing"])

p = figure(x_axis_label='Month', y_axis_label='Sun Hours', title='Monthly Sunlight Duration')
p.line(x='days', y='sun_hours', source=source, line_width=2)

# Dropdown setup
select = Select(title="Select City:", value="Beijing", options=list(city_data.keys()))

# JS callback to swap data
callback = CustomJS(args=dict(source=source, city_data=city_data, select=select), code="""
    const selected = select.value;
    source.data = city_data[selected];
""")

select.js_on_change('value', callback)

show(column(select, p))

Option B: Bokeh Server (For Reading HDF Files)

If you need to read HDF files dynamically when the dropdown changes, you must use Bokeh Server (since only the server can access local files). Here's a simplified example:

from bokeh.models import Select
from bokeh.plotting import figure, curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource
import pandas as pd

# Empty initial source
source = ColumnDataSource(data={'days': [], 'sun_hours': []})

p = figure(x_axis_label='Month', y_axis_label='Sun Hours', title='Monthly Sunlight Duration')
p.line(x='days', y='sun_hours', source=source, line_width=2)

select = Select(title="Select City:", value="Beijing", options=["Beijing", "Shanghai", "Guangzhou"])

def update_plot(attr, old, new):
    # Read HDF data for the selected city
    df = pd.read_hdf('your_data.h5', key=new)  # Adjust key to match your HDF structure
    source.data = {
        'days': df['days'].tolist(),
        'sun_hours': df['sun_hours'].tolist()
    }

# Bind dropdown change to update function
select.on_change('value', update_plot)

# Load initial data
update_plot(None, None, select.value)

curdoc().add_root(column(select, p))

Run this with bokeh serve --show your_script.py

3. Double-Check Data Structure Consistency

Make sure every city's data (whether test or from HDF) has exactly the same column names as your initial ColumnDataSource. If your source expects days and sun_hours, but a city's data uses month or sunlight_hours, the chart won't update—Bokeh can't map mismatched fields.

4. Verify Callback Binding

Ensure you're listening to the right dropdown attribute. The standard attribute to watch is value, so your callback should be attached with select.js_on_change('value', callback) (for CustomJS) or select.on_change('value', update_plot) (for server callbacks).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:28:01