LabelSet / Geographic plots


I was playing around with the geographic plots (of the tutorials section, chapter 9) but I may not understand how it works. Indeed, I tried, just for the fun of learning, to add labels using the LabelSet class from section 4. But it doesn’t work.

Can someone help me to understand that please? Thanks!


import pandas as pd
import numpy as np
from bokeh.models import LabelSet

def wgs84_to_web_mercator(df, lon="lon", lat="lat"):`
"""Converts decimal longitude/latitude to Web Mercator format"""
    k = 6378137
    df["x"] = df[lon] * (k * np.pi/180.0)
    df["y"] = np.log(np.tan((90 + df[lat]) * np.pi/360.0)) * k
    return df

    df = pd.DataFrame(dict(names=["Austin", "NYC", "Btown", "Escalante"], lon=[-97.7431,-74.0059,-86.529167,-111.602222], lat=[30.2672,40.7128,39.162222,37.770278]))

p = figure(tools='pan, wheel_zoom', x_range=x_range, y_range=y_range, 
       x_axis_type="mercator", y_axis_type="mercator")

p.add_tile(WMTSTileSource(url=url, attribution=attribution))['x'], y=df['y'], fill_color='orange', size=10)

labels = LabelSet(x=df['x'], y=df['y'], text=df['names'], level='glyph',
              x_offset=5, y_offset=5, source=df, render_mode='canvas')




The code excerpt is incomplete It lacks sufficient imports (e.g. figure, show, …).

The indentation, which is important in python, appears to be off, e.g I assume the following statements should be at the outermost layer rather than within the wgs84_to_web_mercator() function.

Working around those issues, the problem with the LabelSet() construction is that you have prescribed df['x'], df['y'], and df['names'] for the x, y, and text arguments, respectively, in conjunction with a source argument.

These are not compatible as the argument data you’ve provide are pandas series, but these should be strings which identify the columns of the data you want to use from the source.

I think for your example, you want to try something along the lines of …

labels = LabelSet(x='x', y='y', text='names', level='glyph',
                  x_offset=5, y_offset=5, source=ColumnDataSource(data=df), render_mode='canvas')

and, of course, also add an import statement for the bokeh ColumnDataSource that is used here

from bokeh.models import LabelSet, ColumnDataSource

Hello _jm,

Thanks very much.

Thanks for pointing out the import and indentation issues. These issues were actually fine since imports were made in upstream Jupiter notebook cells, and indentation was a result of copy/paste of the code into the message body.

Importantly, thanks to you, I understand now that the issue was that LabelSet cannot take a Pandas Series as a value for its source argument. I did the modification you suggested and, tadaah, I don’t have any error message anymore !

One thing that is still non working : the labels still don’t appear on the map. In fact, when I scroll « aggressively », I do see them appearing briefly while the map is loading. So the labels seems present but behind the map… I thought that Bokeh add features on the plot in the order they appear in the plot. So I was assuming the the labels would be in the front plan, since this is the last command. Any idea about that?

Have a good day,



Hi Sébastien.

Thanks for clarifying the setup. (I only mentioned those issues unrelated to your question for completeness and to clarify that I could not reproduce your problem by simply running the code. I didn’t want to waste your time in case my guesswork might be addressing something else.)

Bokeh does tend to render things in the order applied, as you surmise. In general, certain objects have default levels so only things with the same level will be layered hierarchically.

In your example, you have set the level for the LabelSet explicitly as glyph. I don’t see why this would result in it being masked by other things. You could try setting it to a “higher” level, e.g. annotation or overlay.

If that doesn’t work, the only other shot-in-the-dark guess is to make certain that everything is using the same units for placement and the labels are not actually outside the plot area (since, it looks like you’re also explicitly setting an x_range and y_range based on variables earlier in your workbook session.

Good luck.

The issue is solved by setting the level to either ‘annotation’ or ‘overlay’, FYI.

Thanks for your additional explanation !

Have a great day,