How can i change the data used by a subplot with a dropdown menu?

Hi guys,
I´m pretty new to working with plotly and i have a problem where you hopefully can help me.
I have two subplots and want to update the data for the y-axis of both plots with a dropdown menu. For the first plot that´s working fine. But not for the second plot.
I think I´m using the wrong key to access the second y-axis.
Here is some example code:

import pandas as pd
import plotly.express as px
from plotly.subplots import make_subplots

# Create demo data
df = pd.DataFrame(dict(A=[1, 2, 3], B=[1, 1, 1], C=[2, 2, 2], D=[3, 3, 3], E=[4, 4, 4]))
df2 = pd.DataFrame(dict(A=[1, 2, 3, 4], B=[5, 5, 5, 5], C=[6, 6, 6, 6], D=[7, 7, 7, 7], E=[8, 8, 8, 8]))

all_df = {"DataA": df, "DataB": df2}

# Create subplots
fig = make_subplots(rows=2, cols=1, vertical_spacing=0.01)
traces = px.line(
    all_df["DataA"],
    x="A",
    y=all_df["DataA"].columns[1:3],
    markers=True,
).data
fig.add_traces(traces, 1, 1)

traces = px.line(
    all_df["DataA"],
    x="A",
    y=all_df["DataA"].columns[3:],
    markers=True,
).data
fig.add_traces(traces, 2, 1)

# Add buttons
buttons = [
    dict(
        method="restyle",
        args=[
            {
                "y": [all_df[n].get(u) for u in all_df[n].columns[1:3]],
                "x": [all_df[n].get("A")],
                "y2": [all_df[n].get(u) for u in all_df[n].columns[3:]],  # I think this is wrong
            },
        ],
        label=n,
    )
    for n in all_df.keys()
]

fig.layout.updatemenus = [{"buttons": buttons}]
fig.show()

I hope you can help me with this.

Hi @Aerandir08 ,

Welcome to the forum!

In the initial display “DataA” options seems ok, but if you choose “DataB” and choose again “DataA”, it will display wrong data.

I suspect this is because of the number of traces you have created per data (which is 4 traces ) does not match which what yaxis they are belong .

To fix that I will set the “y” args into list of array of every column (which is B,C,D,E).
example :
for DataA, args value are

"y" : [all_df["DataA"].get("B"), all_df["DataA"].get("C"), all_df["DataA"].get("D"), all_df["DataA"].get("E")]

if you use list comprehension:

# n="DataA"
"y": [all_df[n].get(u) for u in all_df[n].columns[1:]]

the “x” value is list of all_df[“DataA”].get(“A”), with length is 4

"x" : [ all_df["DataA"].get("A"),  all_df["DataA"].get("A"),  all_df["DataA"].get("A"),  all_df["DataA"].get("A")]

or you can use multiplication:

"x" : [ all_df["DataA"].get("A")] * 4

the last attribute is not “y2” but “yaxis” and “xaxis”

"yaxis": ["y","y","y2","y2"],
"xaxis": ["x","x","x2","x2"]

So your buttons variables can be updated into lines below:

# Add buttons
buttons = [
    dict(
        method="restyle",
        args=[
            {
                "y": [all_df[n].get(u) for u in all_df[n].columns[1:]],
                "x": [all_df[n].get("A")] * 4,
                "yaxis": ["y","y","y2","y2"],
                "xaxis": ["x","x","x2","x2"]
            }
        ],
        label=n,
    )
    for n in all_df.keys()
]

Hope this solve your problem.

2 Likes

@farispriadi Thank you for your help!
I had a complete wrong understanding on how the “args” of the buttons are working.
Thank you for clarification. Now everything works

1 Like