Reputation: 483
Currently, Vega does not support interactive axis labels, i.e. creating a selection via clicking on labels of an axis (see issue 1657), and so neither does Altair.
Therefore I am trying to find a work-around by providing legend selection and changing the appearance of the axis labels.
I am able to color labels conditionally (see code example below).
import altair as alt
from vega_datasets import data
source = data.unemployment_across_industries.url
selection = alt.selection_multi(fields=['series'], bind='legend')
alt.Chart(source).mark_bar().encode(
alt.X('series:N', axis=alt.Axis(labelColor=alt.condition('datum.value == "Finance"', alt.value('red'), alt.value('black')))),
alt.Y('sum(count):Q'),
alt.Color('series:N', scale=alt.Scale(scheme='category20b')),
opacity=alt.condition(selection, alt.value(1), alt.value(0.2))
).add_selection(
selection
)
However, I get an error when trying to use a selection instead of an expression.
alt.X('series:N', axis=alt.Axis(labelColor=alt.condition(selection, alt.value('red'), alt.value('black')))),
Is there any way of connecting the label appearance to a selection (here: bound to the legend)?
Upvotes: 3
Views: 1560
Reputation: 13930
From altair 5 you can use inline expressions as such:
import altair as alt
from vega_datasets import data
source = data.unemployment_across_industries.url
selection = alt.selection_point(fields=['series'], bind='legend')
color_expr = alt.expr(f"datum.value == {selection.name}_series_legend ? 'red' : 'black'")
weight_expr = alt.expr(f"datum.value == {selection.name}_series_legend ? 'bolder' : 'normal'")
chart = alt.Chart(source).mark_bar().encode(
alt.X('series:N').axis(labelColor=color_expr, labelFontWeight=weight_expr),
alt.Y('sum(count):Q'),
alt.Color('series:N', scale=alt.Scale(scheme='category20b')),
opacity=alt.condition(selection, alt.value(1), alt.value(0.2))
).add_params(
selection
)
chart
This only works for a single selection though.
Upvotes: 1
Reputation: 483
Did not find a way to dynamically change the axis labels, but managed to get close to a solution by displaying the axis labels via mark_text
bars = alt.Chart(source).mark_bar().encode(
alt.X('series:N', axis=alt.Axis(labels=False, title="")),
alt.Y('sum(count):Q'),
alt.Color('series:N', scale=alt.Scale(scheme='category20b')),
opacity=alt.condition(selection, alt.value(1), alt.value(0.2))
).add_selection(
selection
)
labels = alt.Chart(source).mark_text(align='right', angle=270).encode(
alt.X('series:N', axis=None),
text='series:N',
opacity=alt.condition(selection, alt.value(1), alt.value(0.2))
).transform_aggregate(
groupby=["series"]
)
(bars & labels).configure(
concat=alt.CompositionConfig(spacing=0)
).configure_view(
strokeWidth=0
)
(Would still love to learn about better solutions.)
Upvotes: 4