Line style conditional on index

My app has a chart (a single line plot) like this

chart = (dash.dcc.Graph(id="chart", style={"width": "100%", "height": "500px"}),)

My data looks like this

table = pd.DataFrame(
    columns=["state", "Sep24", "Oct24", "Nov24", "Dec24", "Jan24", "Feb24", "Mar24"],
    data=[
        ["TX", 1, 2, 3, 4, 5, 6, 7],
        ["AK", 7, 6, 5, 4, 3, 2, 1],
        ["LA", 2, 4, 6, 8, 10, 12, 14],
    ],
)

There is a callback function that updates the chart when the data for Alaska is edited

@dash.callback(Output("chart", "figure"), Input("table", "data"))
def update_chart(table):
    df = pd.DataFrame(table).set_index("state")

    data = [
        {
            "x": df.loc["AK"].index,
            "y": df.loc["AK"].values,
            "line": {"color": "red"},
            "mode": "lines+markers",
        }
    ]

    layout = go.Layout(
        title=go.layout.Title(text="test", xref="paper", xanchor="center"),
        showlegend=False,
    )

    return {"data": data, "layout": layout}

I’d like the line to remain solid for the history (as is) but I want it to be dashed for the forecast. It is conditional formatting of the line style based on the index (x axis). Can that be achieved at all? Alternatively, can I have a different shading of the chart area for the history and the future? If that is not possible either, how do I add a vertical line on the current month to separate the history and the future?

Hi @chon ,

You can split the data into history and forecast , and append new dictionary into data.
And add another trace for create vertical line on the current month to separate the history and the future.

...

data = [
    {
         # solid line for histroy data
        "x": df[df.columns[:3]].loc["AK"].index,
        "y": df[df.columns[:3]].loc["AK"].values,
        "line": {"color": "red"},
        "mode": "lines+markers",
    },
    {
        # dashed line for forecast data
        "x": df[df.columns[2:]].loc["AK"].index,
        "y": df[df.columns[2:]].loc["AK"].values,
        "line": {"color": "red",'dash':'dash'},
        "mode": "lines+markers",
    },
    {
        # line to separate history and forecast
        "x": df[df.columns[2:3]].loc["AK"].index.to_list() * 2,
        "y": [df.loc["AK"].min(), df.loc["AK"].max()],
        "line": {"color": "gray",'dash':'dot'},
        "mode": "lines", 
        "hovertemplate": None, # disable hover data
    },
]
...

3 Likes

Hi @farispriadi , thanks for your response, it works!

I changed your code slightly for the hover data to not appear on the vertical line. I used

"hoverinfo":"skip",

instead of

"hovertemplate": None

I have one remaining issue. The historical line shows “trace 0” next to the hover data and the forecast line shows “trace 1”. How can I change those to “actual” and “forecast” respectively? Or otherwise hide the “trace 0” and “trace 1” (while keeping the hover data)?

This threat suggests the underlying data needs to change but I don’t know how I need to change it.

Hi @chon ,

just add name attribute in the traces data.

data = [
    {
         # solid line for histroy data
        "x": df[df.columns[:3]].loc["AK"].index,
        "y": df[df.columns[:3]].loc["AK"].values,
        "line": {"color": "red"},
        "mode": "lines+markers",
        "name": "History",
    },
    {
        # dashed line for forecast data
        "x": df[df.columns[2:]].loc["AK"].index,
        "y": df[df.columns[2:]].loc["AK"].values,
        "line": {"color": "red",'dash':'dash'},
        "mode": "lines+markers",
        "name": "Forecast",
    },
    {
        # line to separate history and forecast
        "x": df[df.columns[2:3]].loc["AK"].index.to_list() * 2,
        "y": [df.loc["AK"].min(), df.loc["AK"].max()],
        "line": {"color": "gray",'dash':'dot'},
        "mode": "lines", 
        "hovertemplate": None, # disable hover data
    },
]
1 Like

@farispriadi , it works! thank you

1 Like