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

Bokeh无法设置初始范围问题求助(附代码)

问题描述

我是Bokeh绘图初学者,若问题表述浅显还请见谅。尝试用DataFrame中的数据绘制折线图,x、y轴以列表形式提供,但y轴数据中存在None值:

  • 当datapoints列为None时,对应的datapoint_count列是[1]
  • 正常情况下datapoints列应为20个浮点数的列表,datapoint_count列应为1-20的数字列表

期望x轴范围1-20,y轴范围90.0-180.0。运行代码无Python错误,但浏览器开发者工具提示bokeh could not set initial ranges,相关代码如下:

data=df

random_figure = figure(title='random', x_axis_label="Index", y_axis_label="random [ms]",
                         plot_width=800, plot_height=400, output_backend="webgl")

random_figure.add_tools(random_hover)

id_values = data['testcase_id'].drop_duplicates()

data_temp= data[['id', 'datapoints']].copy()
data_temp['datapoint_count'] = None
data_temp['datapoint_count'] = data_temp['datapoint_count'].astype(object)

for indexes, item in data_temp.iterrows():
    if item['datapoints'] is None or str(item['datapoints']) == '[]': # this has nonetype or strings
        item['datapoints'] = [0]
    else:
        item['datapoints'] = [float(x) for x in item['datapoints'].strip('[').strip(']').split(',')]
    iter_nr = 0
    raw_data_count = []
    for each in item['datapoints']:
        iter_nr += 1
        datapoint_count.append(iter_nr)
    data_temp.at[indexes, 'datapoint_count'] = datapoint_count

name_dict_random = {'name': [], 'legend': [], 'label': []}

logging.info('START OF DRAWINGS')

for ind, id in enumerate(id_values):

    it_color = Turbo256[random.randint(0, 255)]

    name_glyph_random = random_figure.line(x='datapoint_count',
                                               y='datapoints',
                                               line_width=2,
                                               legend_label=str(id),
                                               source=data_temp.where(
                                               data_temp['id'] == id).dropna(),
                                               color=it_color)

    name_dict_random['name'].append(name_glyph_random)
    name_dict_random['label'].append(str(id))

logging.info('AFTER DRAWINGS LOOP')

for label in range(len(data.id.unique())):
    name_dict_random['legend'].append(random_figure.legend.items[label])

initial_value = []
options = list(data.id.unique())
for i, name in enumerate(options):
    options[i] = str(name)

for i in range(len(options)):
    if name_dict_random['label'][i] in initial_value:
        name_dict_random['name'][i].visible = True
        name_dict_random['legend'][i].visible = True
    else:
        name_dict_random['name'][i].visible = False
        name_dict_random['legend'][i].visible = False
解决方案

1. 修复数据处理的变量错误

代码里误用了未定义的datapoint_count变量,应该用循环前定义的raw_data_count,否则会导致所有行的计数列表累加,数据彻底混乱:

# 修正后的数据计数逻辑
iter_nr = 0
raw_data_count = []
for each in item['datapoints']:
    iter_nr += 1
    raw_data_count.append(iter_nr)
data_temp.at[indexes, 'datapoint_count'] = raw_data_count

2. 手动指定坐标轴范围

Bokeh自动计算范围失败时,直接显式设置x、y轴范围,从根源解决无法设置初始范围的提示:

random_figure = figure(title='random', x_axis_label="Index", y_axis_label="random [ms]",
                         plot_width=800, plot_height=400, output_backend="webgl",
                         x_range=(1, 20), y_range=(90.0, 180.0))  # 新增固定范围

3. 优化无效数据的处理

当datapoints为None时,你设置的[0]不在期望的y轴范围内,会导致数据点被截断,建议用NaN替代,既不影响范围计算,也不会显示异常点:

if item['datapoints'] is None or str(item['datapoints']) == '[]':
    item['datapoints'] = [float('nan')]  # 用NaN替代0
else:
    item['datapoints'] = [float(x) for x in item['datapoints'].strip('[').strip(']').split(',')]

4. 简化数据源筛选

用直接索引替代where+dropna(),避免不必要的数据缺失,同时建议用ColumnDataSource包装数据源,符合Bokeh最佳实践:

from bokeh.models import ColumnDataSource

# 绘图时的数据源替换
source=ColumnDataSource(data_temp[data_temp['id'] == id])

5. 调整图例初始可见性

initial_value是空列表,导致所有图形默认隐藏,可根据需求设置初始显示的id,比如默认显示第一个:

initial_value = [options[0]]  # 默认显示第一个id的折线

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 13:10:30