Bokeh 无法渲染图表,通常是因为将字符串(如 "0:00")直接用作横坐标;Bokeh 默认将其视为无序类别,但未显式声明分类因子或转换为 datetime 类型,导致坐标轴范围为空、图形不可见。
bokeh 无法渲染图表,通常是因为将字符串(如 `"0:00"`)直接用作横坐标;bokeh 默认将其视为无序类别,但未显式声明分类因子或转换为 datetime 类型,导致坐标轴范围为空、图形不可见。
在您的 Bokeh 应用中,tempo = [f"{i}:00" for i in range(24)] 生成的是字符串列表(如 ["0:00", "1:00", ..., "23:00"])。虽然 Bokeh 支持分类(categorical)横坐标,但它不会自动推断字符串为有序时间标签——必须显式配置 x_range 为 FactorRange,否则绘图区域将因坐标轴范围缺失而空白(即使数据源已正确更新)。
✅ 正确做法:显式设置分类坐标轴
将 figure() 初始化时传入 x_range 参数,明确指定所有时间标签:
from bokeh.models import FactorRange
# 替换原来的 figure 创建方式:
plot_dados = figure(
title="Consumo da Estação ao Longo de 24 Horas",
x_axis_label="Tempo (horas)",
y_axis_label="Energia (kWh)",
x_range=FactorRange(factors=tempo) # ? 关键:显式声明所有分类因子
)同理,为另外两个图表也添加 x_range=FactorRange(factors=tempo):
plot_cargas_bateria = figure(
title="Evolução da Energia da Bateria ao Longo de 24 Horas",
x_axis_label="Tempo (horas)",
y_axis_label="Energia (kWh)",
x_range=FactorRange(factors=tempo)
)
plot_consumo_total = figure(
title="Consumo da Estação + Energia da Bateria ao Longo de 24 Horas",
x_axis_label="Tempo (horas)",
y_axis_label="Energia Total (kWh)",
x_range=FactorRange(factors=tempo)
)⚠️ 注意:若后续需支持交互式缩放、对齐多图横轴,或希望横轴天然具备时间语义(如自动格式化为 HH:mm、支持时间范围选择器),推荐改用 真实 datetime 对象(见下方进阶方案)。
? 进阶方案:使用 datetime 轴(更专业、更灵活)
将字符串时间转换为 datetime 对象(例如当天的 datetime(2024, 1, 1, hour, 0)),并启用 Bokeh 的 datetime 轴自动处理:
from datetime import datetime, date # 生成 datetime 列表(固定日期便于演示) base_date = date(2024, 1, 1) tempo_dt = [datetime.combine(base_date, datetime.min.time().replace(hour=i)) for i in range(24)] # 更新数据源(保持相同结构,仅 x 值改为 datetime) source_dados = ColumnDataSource(data=dict(x=tempo_dt, y=dados)) source_cargas_bateria = ColumnDataSource(data=dict(x=tempo_dt, y=[0]*24)) source_consumo_total = ColumnDataSource(data=dict(x=tempo_dt, y=[0]*24))
此时创建图表时无需手动指定 x_range,Bokeh 会自动识别 datetime 并配置时间轴:
plot_dados = figure(
title="Consumo da Estação ao Longo de 24 Horas",
x_axis_label="Tempo",
y_axis_label="Energia (kWh)",
x_axis_type="datetime", # ? 启用 datetime 轴
width=600,
height=400
)✅ 优势:自动时间格式化(如 00:00, 06:00, 12:00)、支持 pan/zoom 时间范围、与 DatetimeTickFormatter 等高级功能无缝集成。
? 验证与调试建议
- 在 update_plots() 中添加日志,确认数据源是否真实更新:
print("Updated x values:", source_dados.data['x'][:3]) print("Updated y values:", source_dados.data['y'][:3]) - 检查浏览器控制台(F12 → Console)是否有 Range1d 或 FactorRange 相关警告。
- 确保所有图表共用同一组 factors(或 datetime 序列),否则 gridplot 中横轴可能错位。
✅ 总结
| 方案 | 适用场景 | 关键操作 |
|---|---|---|
| FactorRange + 字符串 | 快速原型、纯小时级离散标签、无需时间运算 | x_range=FactorRange(factors=tempo) |
| datetime + x_axis_type="datetime" | 生产环境、需时间语义、未来扩展(如多日数据、实时流) | 将 x 转为 datetime 对象,设 x_axis_type="datetime" |
只要补上 x_range 或切换至 datetime,您的三个柱状图将立即正常渲染——这是 Bokeh 中最常见却易被忽略的“静默失败”原因。

















