Need custom x axis labels to be used in hover text

hi, I have set tickers to use custom labels. How would I use these labels in my hover text? thanks

p.xaxis.ticker = [2500,3000, 3500, 4000, 4500, 5000, 5500]
p.xaxis.major_label_overrides = {2500:'2019', 3000: '2020', 3500: '2021', 4000: '2022', 4500: '2023',5000: '2024',5500: '2024'}

# add hover tool 
hover = HoverTool(tooltips=[('price', '@y{0.}'),('time interval', '@x')])
                              #what to use instead of @x ??????
p.add_tools(hover) 

You best bet here is a CustomJSHover formatter for the hover field.

thanks Bryan here is my attempt so far

from bokeh.plotting import column, figure, show
from bokeh.models import ColumnDataSource, CustomJS, HoverTool, CustomJSHover
import json

x1 = [1, 2, 3, 4, 5, 6, 7, 8] # 8 time periods
y1 = [2278, 2823, 2704, 3225, 3714, 4515, 4076, 4890]

p = figure(width=650, height=600, title='Bokeh line graph with S&P data')
p.xaxis.axis_label = 'time by year'
p.yaxis.axis_label = 'S&P price over 7 years'
p.line(x1, y1, line_width=2)

    #add custom labels to ticks
p.xaxis.ticker = [1,2, 3, 4, 5, 6, 7, 8] 
p.xaxis.major_label_overrides = {1:'2018', 2:'2019', 3:'2020', 4:'2021', 5:'2022',6:'2023',7:'2024',8:'2024.5'}
special = p.xaxis.major_label_overrides

x_custom = CustomJSHover(
    args=dict(special2=special), #passing my custom labels into customJS
    code="""
           //var x = special2;
           //return value + (x);
        return value +(Object.values(special2)); //returns ticker vals not dict vals
          //return "" +(Object.values(special2));

         // var values = Object.keys(special2).map(function(key){
          //return special2[key];
          //});  //this is returning undefined
        
""")

p.add_tools(HoverTool(
    tooltips=[
        ( 'price = ','$y{0.}' ),
        ( 'year = ','$x{custom}' )
    ],
    formatters={'$x': x_custom} 
))
show(p)

@RickD The $x special variable reports the data-space coordinate under the current cursor position, which can (will) be any floating point value, and is not in any way restricted to the special tick locations you have defined. You would need to convert the arbitrary cursor-location-value to one of your special integer values in whatever way is appropriate to your use case (e.g. maybe rounding or truncating or something other kind of binning, it’s up to you)

Alternatively, if all your data points are located only the special tick locations, maybe you really want to use @x for the tooltip variable instead? Rather than the cursor position, that reports the data-space value of the actual coordinate for the line glyph. [1].


  1. In case you use an explicit CDS with a different column name “foo” for the x-coordinate of the line in your real code, then you’d use @foo instead. The @ syntax always references a CDS column name, "x" is just the default column name used when you let Bokeh create a CDS for you internally as the code above does. ↩︎

here is my revised code. Now I get 3 question marks for second tooltip

from bokeh.plotting import column, figure, show
from bokeh.models import ColumnDataSource, CustomJS, HoverTool, CustomJSHover
import json

x1 = [1, 2, 3, 4, 5, 6, 7, 8] # 8 time periods
y1 = [2278, 2823, 2704, 3225, 3714, 4515, 4076, 4890]

p = figure(width=650, height=600, title='Bokeh line graph with S&P data')
p.xaxis.axis_label = 'time by year'
p.yaxis.axis_label = 'S&P price over 7 years'
p.line(x1, y1, line_width=2)

    #add custom labels to ticks
p.xaxis.ticker = [1,2, 3, 4, 5, 6, 7, 8] 
p.xaxis.major_label_overrides = {1:'2018', 2:'2019', 3:'2020', 4:'2021', 5:'2022',6:'2023',7:'2024',8:'2024.5'}
special = p.xaxis.major_label_overrides


x_custom = CustomJSHover(
    args=dict(special2=special), #passing my custom labels into customJS
    code="""
          return value +(Object.values(special2));
    """)

p.add_tools(HoverTool(
    tooltips=[
        ( 'price = ','@y{0.}' ),
        ( 'year = ','@special{custom}' )
    ],
    formatters={'@special': x_custom}
))
show(p)

@offset means ‘take the value from a column named “offset” in the data source’. But you do not have a column named “offset”, which is why the ??? for “unknown” would appear. You probably want @x as I stated above.

With that change, you also probably want something like return special2.get(value) for your JS code.

so we are customizing x via the customJS, thanks Bryan this worked. My first code only needed the correct return value in JS format. Your help is very much appreciated.

on another note, I should not be using x1 and y1 initially, this is sloppy. I read somewhere that bokeh creates its own cds if one is missing like in my case, hence x and y instead of x1 and y1. Then we further customize x by using @x

1 Like