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

Bokeh折线图添加双Y轴报错求助:代码问题排查

问题排查与双Y轴折线图实现方案

代码中的核心问题

  • 错误的折线Y参数格式:你在p.line中把两个Y列写成了嵌套列表[['DOL [m]'], ['DOC [m]']],当使用ColumnDataSource时,每个line方法只能对应一组x/y列,必须分开调用两次line来绘制两条线。
  • 未配置双Y轴:原代码仅使用默认的单个Y轴,无法同时展示两个可能尺度不同的指标(DOL和DOC)。
  • 数据源引用不符合规范:Bokeh要求使用source参数时,x/y必须是数据源中的列名字符串,而非列表或嵌套结构,这直接触发了你看到的报错。

修正后的完整代码

import pandas as pd
from bokeh.models import ColumnDataSource, LinearAxis, Range1d
from bokeh.plotting import figure, show, output_file

output_file('newfile.html')

# 读取数据并处理列名
data = pd.read_excel(r'C:\Users\ASyed\OneDrive - NKT\PythonProject\bokehPractise\newfile\19AJ100429-GC3-FR-003-A1-KP240.000-KP248.831-SL-AT.xlsx', 
                     sheet_name='Listing')
df = pd.DataFrame(data)
df.columns = [x.replace("\n", " ") for x in df.columns.to_list()]

SOURCE = ColumnDataSource(data=df)
p = figure(plot_width=800, plot_height=600, title='DOL Visualization')

# 绘制第一条折线(使用默认Y轴)
p.line(x='KP [km]', y='DOC [m]', source=SOURCE, color='blue', legend_label='DOC [m]')
p.xaxis.axis_label = 'Kilometer Point'
p.yaxis.axis_label = 'DOC [m]'
p.yaxis.axis_label_text_color = 'blue'

# 配置第二个Y轴
# 注册额外的Y轴范围
p.extra_y_ranges = {"dol_range": Range1d(start=df['DOL [m]'].min(), end=df['DOL [m]'].max())}
# 添加第二个Y轴到图表右侧
p.add_layout(LinearAxis(y_range_name="dol_range", axis_label='DOL [m]', axis_label_text_color='red'), 'right')

# 绘制第二条折线(使用额外的Y轴)
p.line(x='KP [km]', y='DOL [m]', source=SOURCE, color='red', legend_label='DOL [m]', y_range_name="dol_range")

# 调整图例位置(可选)
p.legend.location = 'top_left'

show(p)

关键修正说明

  1. 拆分折线绘制:分别调用两次p.line,每次对应一个Y列,确保符合Bokeh的数据源引用规范。
  2. 双Y轴配置:
    • 通过extra_y_ranges注册一个新的Y轴范围,范围基于DOL [m]的最小/最大值自动计算。
    • 使用add_layout将新的LinearAxis添加到图表右侧,并指定对应的范围名称。
    • 绘制第二条折线时,通过y_range_name参数指定使用这个新的Y轴。
  3. 视觉区分:给两条折线和对应Y轴设置不同颜色,方便用户区分两个指标。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:40:24