Bokeh 1.4.0生成HTML无可视化内容问题求助
From your code and issue description, the blank HTML output is caused by several critical mismatches and errors in your implementation. Let's break down the problems and fix them step by step:
Key Issues Identified
Missing
x/yFields in Initial Data Source
Yourfigure.circlecall referencesx="x"andy="y", but the initialColumnDataSource(built fromdata_loaded) doesn't contain these columns. Bokeh fails to render when it can't find required fields.Incorrect Data Type for
fill_alpha
You setalphaas string values ('0.9'/'0.25'), but Bokeh'sfill_alphaexpects numeric (float) values. String types will break rendering.Mixed Workflow: Bokeh Server vs Static HTML
Usingcurdoc().add_root(l)is for Bokeh Server applications. If you're generating a static HTML file, this method won't work—you need to useoutput_fileandshowinstead.Unbound Controls & Missing Filter Logic
Yourx_axisandy_axisdropdowns weren't bound to the update function, and thexVal_maximun_sliderhad no filtering logic to affect the data.
Corrected Code
from os.path import join, dirname import pandas as pd import numpy as np from bokeh.io import output_file, show from bokeh.models import ColumnDataSource, Slider, Div, Select from bokeh.models.tools import HoverTool from bokeh.layouts import layout, column # Synthetic data setup (unchanged) syntetic_columns = ['id_pieza', 'xVar', 'yVar', 'zVar', 'N', 'P', 'vv', 'v'] syntetic_data = [ ['001', 1, 1, 1, 1, 10, 12, 15], ['004', 7.5, 7.1, 5.1, 1, 12, 12, 1.5], ['005', .1, 1, 1.54, 2, 9, 1.2, 1.5], ['006', .51, 1, 1.45, 1, 8.5, 12, 15] ] data_loaded = pd.DataFrame(data=syntetic_data, columns=syntetic_columns) # Fix 1: Use numeric values for alpha instead of strings data_loaded['color'] = np.where(data_loaded['N'] == 1, 'orange', 'grey') data_loaded['alpha'] = np.where(data_loaded['N'] == 1, 0.9, 0.25) # Axis mapping (unchanged) axis_map = { 'Number of pieces': 'N', 'Cost of one unit': 'P', 'X maximum value': 'xVar', 'Y maximum value': 'yVar', 'Z maximum value': 'zVar', } # Controls setup (unchanged) x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Number of pieces") y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Cost of one unit") xVal_maximun_slider = Slider( start=0, end=max(data_loaded['xVar'].values), value=max(data_loaded['xVar'].values), step=0.1, title='X maximum value' ) # Tooltips (unchanged) TOOLTIPS = [ ('Cost per unit', '@P'), ('Number of pieces', '@N'), ('id', '@id_pieza'), ('x value', '@xVar'), ('y value', '@yVar'), ('z value', '@zVar'), ('Volumen de viruta', '@vv') ] # Fix 2: Initialize figure without hardcoding x/y (update will populate them) p = figure( plot_height=600, plot_width=700, title="Interactive Data Visualization", toolbar_location=None, tooltips=TOOLTIPS, sizing_mode="scale_both" ) # Placeholder circle - data will be updated via the update function p.circle(x="x", y="y", source=None, size=7, color="color", line_color=None, fill_alpha="alpha") # Fix 3: Add slider filtering logic def select_data(): selected = data_loaded.copy() # Apply filter from x max slider selected = selected[selected['xVar'] <= xVal_maximun_slider.value] return selected # Fix 4: Update function with complete data source def update(): df = select_data() x_name = axis_map[x_axis.value] y_name = axis_map[y_axis.value] p.xaxis.axis_label = x_axis.value p.yaxis.axis_label = y_axis.value # Create full data source including tooltip fields new_source = ColumnDataSource(data=dict( x = df[x_name], y = df[y_name], color=df['color'], alpha=df['alpha'], P=df['P'], N=df['N'], id_pieza=df['id_pieza'], xVar=df['xVar'], yVar=df['yVar'], zVar=df['zVar'], vv=df['vv'] )) # Update the circle renderer's data source p.renderers[0].data_source = new_source # Fix 5: Bind all controls to the update function controls = [xVal_maximun_slider, x_axis, y_axis] for control in controls: control.on_change('value', lambda attr, old, new: update()) # Layout setup desc = Div(text=open(join(dirname(__file__), "description.html")).read(), sizing_mode="stretch_width") inputs = column(*controls, width=320, height=1000) inputs.sizing_mode = "fixed" l = layout([ [desc], [inputs, p], ], sizing_mode="scale_both") # Initialize data update() # Fix 6: Generate static HTML file output_file("interactive_data_plot.html") show(l)
What Each Fix Does
- Alpha Type Correction: Converts string transparency values to floats so Bokeh can parse them correctly.
- Dynamic Data Source: The
updatefunction creates a completeColumnDataSourcewith all required fields (including tooltip data) instead of relying on missing initial columns. - Control Binding: Adds
x_axisandy_axisto the control list so dropdown selections trigger updates. - Slider Filter Logic: Makes the
xVal_maximun_slideractually filter the data based on the selected maximum x value. - Static HTML Workflow: Uses
output_fileandshowinstead ofcurdocto generate a standalone HTML file that works in Chrome.
Testing Steps
- Ensure
description.htmlexists (replace it with static text like<h2>Interactive Data Plot</h2>if you don't need the external file). - Run the corrected script—it will generate
interactive_data_plot.html. - Open the file in Chrome; you should see the visualization with fully functional controls.
If you still see console errors, verify:
- The path to
description.htmlis correct. - Bokeh 1.4.0 is properly installed (run
pip show bokehto confirm).
内容的提问来源于stack exchange,提问作者Manuel Gijón

