WillsHelm
WillsHelm

Reputation: 21

Altair interactive stacked area plot

I am trying to create an interactive stacked area plot, where the active selection (the one I click in the legend) is the one visible. However, I would like the active selection to be starting from y=0 instead of just highlighted. Is there a way to do this? Furthermore, would it be possible to select multiple values from the legend instead of just one?

import altair as alt
from vega_datasets import data

source = data.unemployment_across_industries.url

selection = alt.selection_multi(fields=['series'], bind='legend',init=[{'series': 'Agriculture'}])

alt.Chart(source).mark_area().encode(
    alt.X('yearmonth(date):T', axis=alt.Axis(domain=False, format='%Y', tickSize=0)),
    alt.Y('sum(count):Q', stack="zero"),
    alt.Color('series:N'),
    opacity=alt.condition(selection, alt.value(1), alt.value(0.1))
).add_selection(
    selection
)

Upvotes: 2

Views: 488

Answers (1)

joelostblom
joelostblom

Reputation: 49054

You can use .transform_filter() to filter the data shown in the chart, and set a constant color domain so that the legend does not automatically change to only show the single filtered series:

import altair as alt
from vega_datasets import data

source = data.unemployment_across_industries()

selection = alt.selection_multi(fields=['series'], bind='legend',init=[{'series': 'Agriculture'}])

alt.Chart(source).mark_area().encode(
    alt.X('yearmonth(date):T', axis=alt.Axis(domain=False, format='%Y', tickSize=0)),
    alt.Y('sum(count):Q', stack="zero"),
    alt.Color('series:N', scale=alt.Scale(domain=source['series'].unique().tolist())),
    opacity=alt.condition(selection, alt.value(1), alt.value(0.1))
).add_selection(
    selection
).transform_filter(
    selection
)

enter image description here

You will notice that the Y-axis label sometimes get outside the chart when changing series. This is because the number of digits used for the y-axis ticks change depending on the selected series and push the label of the chart. To fix this you can do one of the following:

  • Increase the whitespace padding via alt.Chart(source, padding=15) (I think this is the best option).
  • Set a constant y-axis domain with alt.Y(scale=alt.Scale(domain=[0, 16_000])).
  • Tell the chart to resize as selections are made by appending .configure(autosize=alt.AutoSizeParams(resize=True)).

Upvotes: 0

Related Questions