I'm trying to make a stacked bar chart with an interactive legend. I want to be able to select multiple categories from the legend, which will filter the categories shown in the stacked bars.
This is what I have so far:
import altair as alt
import pandas as pd
df = pd.DataFrame(
{
"name": ["Sarah", "Sarah", "Sarah", "Sarah", "Nick", "Nick", "Nick"],
"level": ["A", "B", "B", "C", "A", "B", "C"],
"id": range(7),
}
)
selection = alt.selection_multi(fields=['level'], bind='legend')
alt.Chart(df).mark_bar().encode(
x="count(id)",
y="name",
color=alt.Color(
"level",
),
).add_selection(
selection
).transform_filter(
selection
)
This generates an interactive plot, but when I click on one category in the legend, the other categories disappear from the legend.
I'd like all categories in the legend to stay visible, so I can select multiple categories (such as "B" and "C") using shift-click, and the stacked bar chart will include all the selected categories. Is there any way I can do this?
One direct way to do this is to specify the domain
in the color scale:
color=alt.Color(
"level", scale=alt.Scale(domain=['A', 'B', 'C'])
),
Alternatively, if you want to do it in a way that does not require static specification of the domain, one trick you can use is to layer a transparent version of the full chart behind the filtered version. For example:
base = alt.Chart(df).mark_bar().encode(
x="count(id)",
y="name",
color=alt.Color(
"level",
),
)
background = base.mark_bar(opacity=0)
foreground = base.add_selection(
selection
).transform_filter(
selection
)
background + foreground