BugSquanch
BugSquanch

Reputation: 326

altair dynamic combination of selection conditions

I'm trying to create a chart where it is possible to select combinations of different columns of the data by toggling checkboxes. However I don't always want to display the checkboxes for all the columns. So I want to add the selections to the chart in a 'dynamic' way.

The thing I want to accomplish is that I want to make a pre-selection of which categories I want to visualize (this is done before the altair chart is created). These categories are then added as checkboxes in altair. However the only way I could find to do this is by adding them in a hardcoded way like the "sel1[0] & sel1[1] & sel1[2] & sel1[3] & sel1[4]" in the code below:

sel1 = [
  alt.selection_single(
      bind=alt.binding_checkbox(name=field),
      fields=[field],
      init={field: False}
      )
  for field in category_selection
]
transform_args = {str(col): f'toBoolean(datum.{col})' for col in category_selection}
alt.Chart(df1).transform_calculate(**transform_args).mark_point(filled=True).encode(
    x='dim1',
    y='dim2',
    opacity=alt.condition(
        sel1[0] & sel1[1] & sel1[2] & sel1[3] & sel1[4],
        alt.value(1), alt.value(0)
        )
).add_selection(
    *sel1
)

I have tried doing it like this:

alt.Chart(df1).transform_calculate(**transform_args).mark_point(filled=True).encode(
    x='dim1',
    y='dim2',
    opacity=alt.condition(
        {'and': sel[:2]},
        alt.value(1), alt.value(0)
        )
).add_selection(
    *sel1[:2]
)

But that does not work.

I can't seem to figure out how to achieve something like this with altair. Could someone provide an example on how to do this with checkboxes or help me find another method to achieve the same thing?

TLDR: I basically want to support a variable amount of categories that also supports the ability to create combinations of the categories.
EDIT: Tried to make it more clear what I'm trying achieve with the code.

Upvotes: 1

Views: 613

Answers (1)

jakevdp
jakevdp

Reputation: 86433

It sounds like you want to write the equivalent of this without knowing the length of sel:

sel = [alt.selection_single() for i in range(3)]
combined = sel[0] & sel[1] & sel[2]

For Python operators in general, you can do so like this:

import operator
import functools
combined = functools.reduce(operator.and_, sel)

In Altair, you can alternatively construct the resulting Vega-Lite specification directly:

combined = {"selection": {"and": [s.name for s in sel]}}

Any of these three approaches should lead to identical results when used within an Altair chart.

Upvotes: 1

Related Questions