pythonplotaltair

How to make a selection in the colorbar of an altair plot?


Recently, I started using Altair and liked it a lot. However, I stumbled across something I could not figure out using the docs:

I have a scatter plot that encodes some continuous data as color. Is there a way of selecting a range of these values via the colorbar? Similar to how it is possible to select discrete features in a clickable legend.

I tried the following code:

cars = data.cars()
colorbar_brush = alt.selection_interval(fields=["Acceleration"], bind="legend")

chart = alt.Chart(cars).mark_circle().encode(
    x="Horsepower",
    y="Miles_per_Gallon",
    color=alt.condition(colorbar_brush, "Acceleration:Q", alt.value("lightgray")),
).add_params(
    colorbar_brush,
)

I also tried

colorbar_brush = alt.selection_interval(encodings=["color"], bind="legend")

Both did not work.

Alternatively, it is possible to use separate charts as clickable legends. But how could I create a chart of a color gradient?


Solution

  • As @joelostblom mentioned in his comment you can use a second plot to generate a color scale with a selection interval. I have implemented this using a mark_tick with good results.

    Most of the options for the scale chart's y encoding are only for aesthetics and can be removed / tweaked as desired.

    cars = data.cars()
    
    color_encoding = alt.Color("Acceleration:Q", legend=None)
    selection = alt.selection_interval(encodings=["y"])
    
    chart = (
        alt.Chart(cars)
        .mark_circle()
        .encode(
            x="Horsepower",
            y="Miles_per_Gallon",
            color=alt.condition(selection, color_encoding, alt.ColorValue("lightgray")),
        )
    )
    
    legend_chart = (
        alt.Chart(
            alt.sequence(
                min(cars.Acceleration), max(cars.Acceleration), 0.01, as_="Acceleration"
            )
        )
        .mark_tick(orient="horizontal")
        .encode(
            y=alt.Y(
                "Acceleration:Q",
                axis=alt.Axis(
                    orient="right",
                    ticks=False,
                    grid=False,
                    titleAngle=0,
                    titleAnchor="end",
                    titleAlign="center",
                    titleBaseline="bottom",
                    titleY=-10,
                    tickCount=3
                ),
            ).scale(zero=False, padding=0),
            color=color_encoding,
        )
    ).add_params(selection)
    
    chart | legend_chart
    

    Chart of Answer