如何为Bokeh多列折线图配置HoverTool交互工具
解决Bokeh多折线图HoverTool显示所有指定列信息的问题
我编写了一个以Pandas DataFrame为数据源,绘制指定列多折线图的Bokeh函数,现需为图表添加HoverTool工具,显示所有指定列的信息。多次尝试通过循环实现均失败,附上代码及最后一次尝试的代码,请求解决方案。
原代码:
import pandas as pd import numpy as np from bokeh.plotting import figure, show from bokeh.models import ColumnDataSource df = pd.DataFrame(np.random.randint(0,100,size=(10, 5)), columns=list('ABCDF')) source = ColumnDataSource(df) colors = ['blue', 'green', 'red', 'orange', 'brown', 'black'] ###Plotting function def plot(df, col_n): p = figure(height=300, width=300) for i, c in zip(col_n, colors): p.line(source=source, x= 'index', y=str(i), color=c) return p ttt = plot(df, ['A', 'B', 'C', 'F']) show(ttt)
最后一次尝试的代码:
n = range(len(col_n)) for i, x in zip(col_n, n): hover1 = HoverTool(tooltips=[("Date", "@index{%d/%m/%Y}"), ("Price_"+str(i), '"""@"+str(i)+"{€ %.2f}"""')], formatters={'@date': 'datetime'}, mode='vline')
正确实现方案
无需循环创建多个HoverTool,只需一次性构建包含所有指定列的tooltips列表,再添加到图表中即可。以下是修改后的完整代码:
import pandas as pd import numpy as np from bokeh.plotting import figure, show from bokeh.models import ColumnDataSource, HoverTool df = pd.DataFrame(np.random.randint(0,100,size=(10, 5)), columns=list('ABCDF')) # 将DataFrame索引转为显式列,确保ColumnDataSource能识别 df['index'] = df.index source = ColumnDataSource(df) colors = ['blue', 'green', 'red', 'orange', 'brown', 'black'] ### 改进后的绘图函数 def plot(df, col_n): p = figure(height=300, width=300) # 绘制所有指定列的折线 for i, c in zip(col_n, colors): p.line(source=source, x='index', y=str(i), color=c) # 构建HoverTool的提示项列表 tooltips = [("索引", "@index")] # 循环添加所有指定列的提示信息 for col in col_n: tooltips.append((f"Price_{col}", f"@{col}{{€ %.2f}}")) # 创建HoverTool并添加到图表 hover = HoverTool(tooltips=tooltips, mode='vline') p.add_tools(hover) return p ttt = plot(df, ['A', 'B', 'C', 'F']) show(ttt)
关键说明
- 索引处理:将DataFrame的
index转为显式列,避免ColumnDataSource无法读取隐式索引的问题。 - 提示项构建:通过循环一次性生成所有列的提示项,用f-string简化字符串拼接,避免原代码中引号嵌套的语法错误。
- 单一HoverTool实例:仅需创建一个HoverTool,设置
mode='vline'即可在垂直悬停时显示所有列的对应值,循环创建多个HoverTool会导致工具冲突,无法正常显示。 - 日期格式适配:如果你的
index是日期类型,只需将提示项改为("日期", "@index{%d/%m/%Y}"),并添加formatters={'@index': 'datetime'}参数即可。
内容的提问来源于stack exchange,提问作者cJc
相关产品推荐
相关产品推荐

