gmaps icon indicating copy to clipboard operation
gmaps copied to clipboard

Ability to add a legend to marker and symbol layers?

Open Xiangyu-C opened this issue 7 years ago • 3 comments

Hi Pascal, I am using your great package on a data science project. I need to use symbol_layer to add crimes from different years. I couldn't find a way to show a legend to indicate what color is from what year. Is there a way to do it? Thanks.

Here is the pseudocode if you will:

  1. Loop over crime coordinates from 10 year data
  2. Add a symbol layer per year with a different color and end loop
  3. Add a legend to indicate different years.
  4. Show the figure.

Xiangyu-C avatar Dec 23 '17 21:12 Xiangyu-C

Hi Pascal, I am using your great package on a data science project

Great! Thanks for the feedback.

At the moment, there is no canned way to add a legend to a symbol layer (this would make a great addition, PRs welcome!). You are probably best off drawing your own using jupyter widgets. Since gmaps maps are themselves Jupyter widgets, you can use them as building blocks for more complex visualisations.

For instance:

import random

from matplotlib.cm import tab10 # Use the matplotlib tab10 colormap
from matplotlib.colors import to_hex

import ipywidgets as widgets

gmaps.configure(api_key='...')

def gen_random_locations(npoints):
    """
    Generate `npoints` random locations in the US
    """
    latitudes = [random.uniform(32.7, 48.6) for _ in range(npoints)]
    longitudes = [random.uniform(-124.5, -77.0) for _ in range(npoints)]
    return list(zip(latitudes, longitudes))
    
# These are the 10 years that make up your data
years = [1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006]
assert len(years) == 10

data = {year: gen_random_locations(10) for year in years}
colors = {year: to_hex(tab10(iyear)) for iyear, year in enumerate(years)} # generate a colour for each year

# Some CSS hackery to draw a circle of that color next to the year
legend_template = '<span style="color: {color}; font-size: 2em; vertical-align: bottom;">&#9679;</span> {year}'

def draw_map_with_legend():
    figure = gmaps.figure()
    legend_entries = []
    for iyear, year in enumerate(years):
        locations = data[year]
        color = colors[year]
        points_layer = gmaps.symbol_layer(
            locations, 
            fill_color=color, 
            stroke_color=color, 
            fill_opacity=0.7,
            stroke_opacity=0.7
        )
        figure.add_layer(points_layer)
        legend_entries.append(legend_template.format(color=color, year=year))
    legend = widgets.HBox(
        [widgets.HTML(legend_entry) for legend_entry in legend_entries],
        layout=widgets.Layout(width='100%', justify_content='space-between')
    )
    return widgets.VBox([figure, legend])

draw_map_with_legend()
screen shot 2017-12-25 at 07 54 01

Note the following:

  • we use the HBox and VBox widgets to stack widgets (like maps and legend entries).
  • we use a matplotlib colormap to get some colors that go well together. I chose the tab10 at random. See the matplotlib docs for other color maps. You can also just choose arbitrary colors, obviously.

pbugnion avatar Dec 25 '17 07:12 pbugnion

For anyone interested in implementing this.

One avenue to consider is using the feature built into google maps. Alternatively, we add a legend box to the figure that can be populated by layers, much like the toolbar box.

pbugnion avatar Dec 25 '17 08:12 pbugnion

Thank you. I am quite new to this. I will try your code and learn more about the widgets in jupyter.

Xiangyu-C avatar Dec 25 '17 15:12 Xiangyu-C