question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add support for legend_field with geo data

See original GitHub issue

ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)

  • bokeh version 1.4.0
  • python 3.7
  • Windows 10

Description of expected behavior and the observed behavior

I want to add a legend to my plot of Geodata. In particular, I plot point data with different coloring according to a categorical variable in my data set. I transform my geopandas to to a GeoJsonDataSource accordingly. Everything works well, except creating the legend.

When I follow the following example: https://docs.bokeh.org/en/latest/docs/user_guide/annotations.html#legends I get the following error:

Column to be grouped does not exist in glyph data source.

Even though I include the source in the glyph method, i.e.

p1.circle(
    "x",
    "y",
    source=geosource,
    fill_color={"field": "share_prot", "transform": color_mapper},
    line_color="black",
    line_alpha=0.5,
    line_width=0.3,
    alpha=0.6,
    #size=2,
    legend_group="share_prot"
)

Complete, minimal, self-contained example code that reproduces the issue

from bokeh.io import output_file, show
from bokeh.models import GeoJSONDataSource
from bokeh.plotting import figure
from bokeh.sampledata.sample_geojson import geojson
import json

data = json.loads(geojson)
for i in range(len(data['features'])):
    data['features'][i]['properties']['Color'] = ['blue', 'red'][i%2]

geo_source = GeoJSONDataSource(geojson=json.dumps(data))
p = figure(background_fill_color="lightgrey")
p.circle(x='x', y='y', size=15, color='Color', alpha=0.7, source=geo_source, legend_group='Color')

show(p)

Stack traceback and/or browser JavaScript console output

<ipython-input-133-afa857e8c002> in <module>
     12 color_mapper = CategoricalColorMapper(factors=share_prot.unique(), palette=palette)
     13 p = figure(background_fill_color="lightgrey")
---> 14 p.circle(x='x', y='y', size=15, color='Color', alpha=0.7, source=geo_source, legend_group='Color')
     15 
     16 show(p)

fakesource in circle(self, x, y, **kwargs)

~\Anaconda3\envs\adv\lib\site-packages\bokeh\plotting\helpers.py in func(self, **kwargs)
    930 
    931         if legend_kwarg:
--> 932             _update_legend(self, legend_kwarg, glyph_renderer)
    933 
    934         self.renderers.append(glyph_renderer)

~\Anaconda3\envs\adv\lib\site-packages\bokeh\plotting\helpers.py in _update_legend(plot, legend_kwarg, glyph_renderer)
    487     kwarg, value = list(legend_kwarg.items())[0]
    488 
--> 489     _LEGEND_KWARG_HANDLERS[kwarg](value, legend, glyph_renderer)
    490 
    491 

~\Anaconda3\envs\adv\lib\site-packages\bokeh\plotting\helpers.py in _handle_legend_group(label, legend, glyph_renderer)
    454         raise ValueError("Cannot use 'legend_group' on a glyph without a data source already configured")
    455     if not (hasattr(source, 'column_names') and label in source.column_names):
--> 456         raise ValueError("Column to be grouped does not exist in glyph data source")
    457 
    458     column = source.data[label]

ValueError: Column to be grouped does not exist in glyph data source

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
hmanuel1commented, Apr 17, 2020

I ran into the same issue with the custom legend for geopandas. This is working somewhat for me. It will work if you don’t expect x_range or y_range to change. Trying to figure out how to prevent the “fake quads” from rendering, so it will not affect x_range or y_range when replacing the content of a figure. It will be nice that manual legends can be implemented without having to specify an actual coordinate pair in the plot.

image

from bokeh.io import show
from bokeh.models import LogColorMapper, Legend
from bokeh.palettes import Viridis6 as palette
from bokeh.plotting import figure
from bokeh.sampledata.unemployment import data as unemployment
from bokeh.sampledata.us_counties import data as counties

palette = tuple(reversed(palette))

counties = {
    code: county for code, county in counties.items() if county["state"] == "tx"
}

county_xs = [county["lons"] for county in counties.values()]
county_ys = [county["lats"] for county in counties.values()]

county_names = [county['name'] for county in counties.values()]
county_rates = [unemployment[county_id] for county_id in counties]
color_mapper = LogColorMapper(palette=palette)

data=dict(
    x=county_xs,
    y=county_ys,
    name=county_names,
    rate=county_rates,
)

TOOLS = "pan,wheel_zoom,reset,hover,save"

p = figure(
    title="Texas Unemployment, 2009", tools=TOOLS,
    x_axis_location=None, y_axis_location=None,
    tooltips=[
        ("Name", "@name"), ("Unemployment rate", "@rate%"), ("(Long, Lat)", "($x, $y)")
    ])
p.grid.grid_line_color = None
p.hover.point_policy = "follow_mouse"

p.patches('x', 'y', source=data,
          fill_color={'field': 'rate', 'transform': color_mapper},
          fill_alpha=0.7, line_color="white", line_width=0.5)

"""
 custom geo legend that works with this example
 with geopandas dataframe see the next commented block
"""
xq, yq = data['x'][0][0], data['y'][0][0]

"""
 for geopandas dataframe you can do the same by selecting a coord of a valid polygon
 the following line will take the coordinate pair xq and yq from a
 geopandas dataframe (gdf) polygon...
(xq, yq) = list(gdf['geometry'].values[0].envelope.centroid.coords)[0]
"""

legend_names = []
for i in range(len(palette)):
    legend_names.append(f"Legend Item {i}")

items = []
for i in reversed(range(len(palette))):
    items += [(legend_names[i], [p.quad(top=yq, bottom=yq, left=xq,
              right=xq, fill_color=palette[i])])]

p.add_layout(Legend(items=items, location='bottom_left',
             title="Unemployment Rate:"))

show(p)
0reactions
meenurajapandiancommented, Mar 3, 2020

I came across this while looking for a way to add a legend to a heatmap with a linear colormapper that uses a GeoJSONDataSource. But the legend_field does not work for me either.

The figure is basically this: p.patches('xs', 'ys', fill_color={'field': 'some_field', 'transform': mapper}, source=geo_src, legend_field='some_field')

some_field is a feature of each patch and geo_src is a GeoJSONDataSource. Color is mapped as required but not able to add legend. Is there a work around to get the legend?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Adding annotations — Bokeh 2.4.3 Documentation
This way, you can create legend entries based on groups of glyphs. To use data from a column of a ColumnDataSource to generate...
Read more >
Working with legends—ArcMap | Documentation
ArcMap provides a wizard in which you can add a legend to your map. ... When layers in a data frame are made...
Read more >
Solved: Re: How to Map Multiple GEO Codes Address on One M ...
Power BI map allows you to at Log lat. Also, you can add a field in the legend(field having New/old in your case)...
Read more >
Adding tooltips and legends | TileMill - GitHub Pages
Select the “Earthquakes” layer to use it for interaction. TileMill only supports one interactive layer at a time. The data fields for the...
Read more >
Formatting Data in Power BI Desktop Visualizations
Add a “Balance” column to the Values field, and a “Geography” column to the “Legend” field. You will see a “Pie” chart that...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found