[Python] Multiple time series chart in altair with selectable time series

Discussão em 'Python' iniciado por Stack, Maio 6, 2025.

  1. Stack

    Stack Membro Participativo

    I want to make a chart in altair with the following properties:

    • It shows multiple time series
    • I can select which time series are displayed by clicking on the legend
    • If a series is unselected in the legend, then it is not displayed in the plot
    • If a series is unselected in the legend, then you can still see it in the legend
    • Colours of lines remain consistent, no matter which time series are selected or unselected

    An LLM supplied me with the following code which doesn't do what I want

    import pandas as pd
    import altair as alt

    dates = pd.date_range(start="2023-01-01", periods=10)
    data = {
    "Date": dates.tolist() * 3,
    "Value": [10, 20, 15, 30, 25, 35, 40, 45, 50, 55] +
    [5, 15, 10, 20, 15, 25, 30, 35, 40, 45] +
    [2, 12, 8, 18, 14, 22, 28, 32, 38, 42],
    "Device": ["Device A"] * 10 + ["Device B"] * 10 + ["Device C"] * 10
    }
    df = pd.DataFrame(data)

    # Create a selection object for the legend
    aselection = alt.selection_multi(fields=["Device"], bind="legend")

    # Create the Altair chart
    achart = alt.Chart(df).mark_line().encode(
    x="Date:T",
    y="Value:Q",
    color="Device:N" # Keep the color consistent
    ).transform_filter(
    aselection # Filter data based on the selection
    ).add_selection(
    aselection
    ).properties(
    title="Interactive Time Series Plot"
    )

    achart


    It seems that the transform_filter makes an unselected series vanish from the chart, but this also forces it to vanish from the legend. I want it to vanish from the chart but stay in the legend.

    Alternatively, I have the following code

    chart = alt.Chart(df).mark_line().encode(
    x="Date:T",
    y="Value:Q",
    color="Device:N", # Keep the color consistent
    opacity=alt.condition(aselection, alt.value(1), alt.value(0.2)) # Hide unselected lines
    ).add_selection(
    aselection
    ).properties(
    title="Interactive Time Series Plot"
    )


    Now the legend works in the way I want (you can select multiple series by shift-clicking) but an unselected time series is still displayed on the chart, just in a paler colour. If I make the chart interactive, then the end user will often end up clicking on an unselected series by accident, so this is definitely not what I want either.

    Edit: the following almost works, but the problem is that the user can still affect the selection by clicking on the plot. Is there a way to make the plot interactive but disable clicking?

    achart = alt.Chart(df).mark_line().encode(
    x="Date:T",
    y="Value:Q",
    color="Device:N", # Keep the color consistent
    ).transform_filter(
    aselection
    ).add_selection(aselection)

    chart2 = alt.Chart(df).encode(
    x="Date:T",
    y="Value:Q",
    color="Device:N", # Keep the color consistent # Hide unselected lines
    ).mark_line(opacity=0).properties(
    title="Interactive Time Series Plot"
    )

    chart2 + achart.interactive()


    Is there a way to do what I want?

    Continue reading...

Compartilhe esta Página