(Python) Get only first index value for HoverTool

Hello,

I would like to ask, if it’s possible to create tooltip, using HoverTool, where tooltip field will be 0 index of column in dataframe?

I create pandas Dataframe, which then I send to ColumnDataSource. In my dataframe I have several columns with data, and 2 columns (let’s say it’s called “Mode” and “Date”) which contains value only on [0] index. When I create hover instance and add this to the figure, it obviously doesn’t show values for index different than 0. Obviously I might fill up all rows with this value but this is something I’d like to avoid.

Here’s how my code looks like:

import pandas as pd
from datetime import datetime
from bokeh.models import HoverTool
from bokeh.plotting import figure, ColumnDataSource
from bokeh.resources import CDN
from bokeh.embed import file_html

x = pd.Series([1,2,3,4,5,6], name='x')
y = pd.Series([4,3,5,4,3,2], name='y')
df = pd.concat([x, y], axis=1)

df.loc[df.index[0], 'Date'] = datetime.today()
df.loc[df.index[0], 'Mode'] = 'CC'
df.fillna('', inplace=True)

source = ColumnDataSource(df)
hover = HoverTool(
    tooltips=[
        ("Mode", "@Mode"),
        ("Date", "@Date{%F}"),
        ("y", "$y"),
        ("x", "$x")
    ],
    formatters={'Date': 'datetime'}
)
fig = figure()
fig.add_tools(hover)
fig.scatter(x='x', y='y', source=source, marker='square', size=8)
html = file_html(fig, CDN, "x vs y")
with open('test.html', 'w+') as f:
    f.write(html)

Is there any way, that I can set value to specified index of column inside HoverTool?

@Rromo Hi, welcome to the Discource. First two things:

  • Please edit your post to use the code-formatting ability of the Disourse. That will allow for preserving indentation, and you also keep the code verbatim (i.e can leave the @Mode exactly the way it should be). You can either enclose code blocks in triple-backticks ``` or else use the little </> symbol on the GUI editor to format code blocks.

  • I don’t really understand what you are trying to achieve. I am not familiar with the terminology “0 index of column” of a DataFrame. Please elaborate a bit on what exactly you are trying o accomplish. You might also include some fake or sample data that is representative of the actual data you are dealing with.

Hello, thanks for your reply. I’ve already modified my code to working example.

In this example I modify dataframe in the way, that there is only one row of data in columns “Date” and “Mode”. I want to avoid creating new column which is filled with the same value from top to bottom.

If you open the plot, you can notice, that when you hover over 1st point, it will show today’s date in Date field and Mode field is set to “CC”, and when you hover over next points, it will not show correct values for these fields. My question - is it possible, to have some of the fields in tooltip fixed only to first index of the dataframe’s column?

I’m still confused about your usage and situation. DataFames always have columns that are all the same length. So if you have some value that applies to all rows in DataFrame, but don’t want to have a column filled with that value, then it seems to me that you should not have a column at all.

In any case, if you want to fix values to display in hover tooltips, you can pass them as string literals:

hover = HoverTool(
    tooltips=[
        ("Mode", "MY SPECIAL MODE VALUE"),
        ("Date", "SOME SPECIFIC DATE"),
        ("y", "$y"),
        ("x", "$x")
    ],
    formatters={'Date': 'datetime'}
)

Tooltip fields may have fields like @foo that reference CDS columns, but they don’t have to. If you know the single fixed value you want displayed for all points ahead of time (which you must in this case, since you were going to put it in the first row of the DataFrame), you can put it the tooltip string ahead of time, explicity.

If you really want a column with only a single valid value in one row, and a hover that always looks up that one row, you could potentially do that in a CustomJSHover. But that’s a lot of work for no gain (over the suggestion above) as far as I can tell.