Filter altair heatmap with heat shading and text value

Viewed 966

I'm trying to create a heatmap using the Altair lib, but I'm looking to filter my data with a slider for different views. The slider works fine with the standard color only heatmap, but when I try to add text to the boxes to describe the values in each cell I get the javascript error below. (Adding the text to the heatmap works fine without any filter slider.)

import altair as alt
import pandas as pd
source = pd.DataFrame({'year':[2017, 2017, 2018, 2018],
                       'age':[1, 2, 1, 2],
                       'y':['a', 'a', 'a', 'a'],
                       'n':[1, 2, 3, 4]})

slider = alt.binding_range(min=2017, max=2018, step=1)
select_year = alt.selection_single(name="my_year_slider", fields=['year'], bind=slider)
base = alt.Chart(source).add_selection(select_year).transform_filter(select_year)

heatmap = base.mark_rect().encode(
    x='age:O',
    y='y:O',
    color='n:Q')

text = base.mark_text(baseline='middle').encode(
    x='age:O',
    y='y:O',
    text='n:Q')

heatmap + text

This returns Javascript Error: Duplicate signal name: "my_year_slider_tuple"

1 Answers

Because you added the selection to the base chart and then layered two copies of it, the selection is defined twice. The solution is to only define the selection once; something like this:

import altair as alt
import pandas as pd
source = pd.DataFrame({'year':[2017, 2017, 2018, 2018],
                       'age':[1, 2, 1, 2],
                       'y':['a', 'a', 'a', 'a'],
                       'n':[1, 2, 3, 4]})

slider = alt.binding_range(min=2017, max=2018, step=1)
select_year = alt.selection_single(name="my_year_slider", fields=['year'], bind=slider)

base = alt.Chart(source).encode(
    x='age:O',
    y='y:O',
).transform_filter(select_year)

heatmap = base.mark_rect().encode(color='n:Q').add_selection(select_year)

text = base.mark_text(baseline='middle').encode(text='n:Q')

heatmap + text
Related