Angela
Angela

Reputation: 235

Bokeh HoverTool Shows "???"

I'm getting into the Bokeh library with Python, but I'm having some trouble. I have the following code from the Bokeh tutorial website:

from bokeh.plotting import figure 
from bokeh.io import output_notebook, show
output_notebook()
from bokeh.sampledata.autompg import autompg
from bokeh.models import HoverTool
from bokeh.plotting import ColumnDataSource

grouped = autompg.groupby("yr")
mpg2 = grouped["mpg"]
avg = mpg2.mean()
std = mpg2.std()
years = list(grouped.groups.keys())
american = autompg[autompg["origin"]==1]
japanese = autompg[autompg["origin"]==3]

p = figure(title="MPG by Year (Japan and US)")

p.vbar(x=years, bottom=avg-std, top=avg+std, width=0.8, 
       fill_alpha=0.2, line_color=None, legend="MPG 1 stddev")

p.circle(x=japanese["yr"], y=japanese["mpg"], size=10, alpha=0.5,
         color="red", legend="Japanese")

p.triangle(x=american["yr"], y=american["mpg"], size=10, alpha=0.3,
           color="blue", legend="American")

p.legend.location = "top_left"
show(p)

It works, but I'd like to add the functionality that when you hover over a point, it displays the horsepower. What I tried is

grouped = autompg.groupby("yr")
mpg = grouped["mpg"]
avg = mpg.mean()
std = mpg.std()
years = list(grouped.groups.keys())
american = autompg[autompg["origin"]==1]
japanese = autompg[autompg["origin"]==3]

source = ColumnDataSource(data=
   dict(autompg)
)

hover1 = HoverTool(tooltips=[("hp", "@hp")])


p = figure(title="MPG by Year (Japan and US)",tools=[hover1])

p.vbar(x=years, bottom=avg-std, top=avg+std, width=0.8, 
       fill_alpha=0.2, line_color=None, legend="MPG 1 stddev")

p.circle(x=japanese["yr"], y=japanese["mpg"], size=10, alpha=0.5,
         color="red", legend="Japanese")

p.triangle(x=american["yr"], y=american["mpg"], size=10, alpha=0.3,
           color="blue", legend="American")

p.legend.location = "top_left"
show(p)

So defining a HoverTool that I hoped would do just that. Unfortunately, it only displays "hp: ???" for every entry. I think it's a problem with the data source, but I don't have much experience here and can't figure it out myself. I've tried the source without dict(), and I've tried to set it as american or japanese, but none of this made a difference.

Thanks!

Upvotes: 6

Views: 10897

Answers (1)

bigreddot
bigreddot

Reputation: 34568

You need to pass the source to the glyph functions, and refer to the column names for the coordinates. If you pass literal lists/arrays (as you are doing above) to circle, etc. then Bokeh will create a CDS for that data under the covers, but only with the just the data you pass to the glyph function (i.e. without extra columns like "hp"). Since you are trying to plot different glyphs for different subsets of the data, the simplest thing will be to use a CDSView to group them on the client. Something like this instead:

from bokeh.plotting import figure
from bokeh.io import show
from bokeh.sampledata.autompg import autompg
from bokeh.models import ColumnDataSource, CDSView, GroupFilter, HoverTool

p = figure()

# Bokeh factors must be strings
autompg.origin = [str(x) for x in autompg.origin]

source = ColumnDataSource(autompg)

# view for just japanese origin
japanese = CDSView(source=source, filters=[GroupFilter(column_name='origin', group="1")])

# draw circles for just the japanese view
p.circle(x="yr", y="mpg", size=10, alpha=0.5, color="red", legend="Japanese",
         source=source, view=japanese)

# view for just japanese origin
american = CDSView(source=source, filters=[GroupFilter(column_name='origin', group="3")])

# draw triangles for just the american view
p.triangle(x="yr", y="mpg", size=10, alpha=0.5, color="blue", legend="american",
         source=source, view=american)

p.add_tools(HoverTool(tooltips=[("hp", "@hp")]))

show(p)

enter image description here

Upvotes: 7

Related Questions