altair icon indicating copy to clipboard operation
altair copied to clipboard

Improve the syntax for conditions with multiple predicates

Open mattijn opened this issue 2 years ago • 15 comments

Questioned in SO: How to create an altair condition with three or more choices [duplicate] and SO: Combine hover and click selections in Altair and surfaced in https://github.com/altair-viz/altair/pull/2756

It is currently possible to write a condition with single predicate:

import altair as alt
from vega_datasets import data

cars = data.cars.url

base = alt.Chart(cars).mark_tick().encode(x='Miles_per_Gallon:Q')

# condition with single predicate
base.encode(color=alt.condition(
    alt.datum.Origin == 'Europe', 
    alt.value('green'), # when true
    alt.value('red') # when false
    )
)

image

And one can combine multiple selections into a single predicate as is written here: https://altair-viz.github.io/user_guide/interactions.html#composing-multiple-selections

To combine multiple predicates within a single condition one can define a dict with a list of conditions as such:

# condition with multiple predicates
color_condition = {
    "condition": [
        {"test": "datum.Origin === 'Europe'", "value": "green"},
        {"test": "datum.Origin === 'Japan'", "value": "blue"},
    ],
    "value": "red",
}
base.encode(
    color=color_condition
)

image

But using an alt.condition() this is not possible.

Maybe something as such should be supported:?

base.encode(color=alt.condition(
    predicate=[
        alt.pred(expr=alt.datum.Origin == "Europe", if_true=alt.value("green")),
        alt.pred(expr=alt.datum.Origin == "Japan", if_true=alt.value("blue")),
    ],
    if_false=alt.value("red")
    )
)

mattijn avatar Dec 17 '22 18:12 mattijn

@joelostblom do you still have a ideas for this? I like to use this to combine a highlight and click condition. Something quite common, but the approach is not clear yet.

We also can also implement a list of conditions, like [alt.condition(), alt.condition()], or a new alt.conditions() (plural) or change the current alt.condition() so it by defaults support multiple predicates or do something as alt.condition() + alt.condition().

Edit; Or

alt.condition() * alt.condition()

mattijn avatar Feb 26 '23 14:02 mattijn

Hmm I don't really have a good idea of what is prefereable here, other than in terms of what I would find nice to type myself, which I think would be similar to the last example in your first comment, something like this:

base.encode(
    color=alt.condition([
        (alt.datum.Origin == "Europe", alt.value("green")),
        (alt.datum.Origin == "Japan", alt.value("blue"))
    ],
    alt.value("red")
)

joelostblom avatar Feb 27 '23 05:02 joelostblom

Partly related https://github.com/altair-viz/altair/issues/695

joelostblom avatar Mar 02 '23 02:03 joelostblom