0

I want to create a line plot in which the underlying data can be selected over a drop down menu. The data is in a pandas dataframe and I am using plotly_express.

I tried to use this post as a basis but it does not use plotly_express and the data is not in a pandas dataframe.

I have this code in which I define a data1 and data2 and then put those into the buttons. I am converting those dataframes into a dictionnary because if not I will have the error that dataframes were not "json-able".

# making two new dataframes out of the all-data dataframe (for drop down select)
dfe_deworming=dfe.loc['Deworming needed'].reset_index()
dfe_anemia=dfe.loc['Anemia'].reset_index()

# making the parameters for each button

#button 1
data1=dict(dfe_deworming)
x1=dfe_deworming.Month
y1=dfe_deworming.Count
color1=dfe_deworming.Facility

#button2
data2=dict(dfe_anemia)
x2=dfe_anemia.Month
y2=dfe_anemia.Count
color2=dfe_anemia.Facility

#initial plot
fig_deworming = px.line(data_frame=data1,x=x1,y=y1,color=color1)

# update menus
updatemenus = [
    {
        'buttons': [
            {
                'method': 'restyle',
                'label': 'Deworming needed',
                'args': [
                    {'data_frame':[data1],'x': [x1],'y':[y1],'color':[color1]},
                ]
            },
            {
                'method': 'restyle',
                'label': 'Anemia',
                'args': [
                    {'data_frame':[data2],'x': [x2],'y':[y2],'color':[color2]},
                ]
            }
        ],
        'direction': 'down',
        'showactive': True,
    }
]


fig_deworming.update_layout(
    updatemenus=updatemenus
)

fig_deworming.update_traces(mode='markers+lines')

fig_deworming.show()

In its initial state it looks good. However if I try to select an option, all lines get exactly the same dataset. It could be the combination of all the different datasets.

Those pictures illustrate the problem:

First option of the drop down menu after first selection

Second option of the drop down menu after second selection

Aneho
  • 118
  • 7

1 Answers1

0

fundamentally you need to use graph object parameter structure for updatemenus

  • have generated a dataframe that appears to match your structure
  • create the graph using plotly express
  • generate updatemenu which are parameters you would pass to go.Scatter
  • used a list comprehension as each menu is really the same
  • finally fix an issue with trace generated by plotly express for hovertemplate
import numpy as np
import pandas as pd
import plotly.express as px

# generate a dataframe that matches structure in question
dfe = (
    pd.DataFrame(
        {
            "Month": pd.date_range("1-jan-2020", freq="M", periods=50).month,
            "Facility": np.random.choice(["Deworming needed", "Anemia"], 50),
            "Count": np.random.randint(5, 20, 50),
        }
    )
    .groupby(["Facility", "Month"], as_index=False)
    .agg({"Count": "sum"})
)

# the line plot with px...
fig = px.line(
    dfe.loc[dfe.Facility.eq("Deworming needed")], x="Month", y="Count", color="Facility"
)


# fundametally need to be working with graph object parameters not express parameters
updatemenus = [
    {
        "buttons": [
            {
                "method": "restyle",
                "label": f,
                "args": [
                    {
                        "x": [dfe.loc[dfe.Facility.eq(f), "Month"]],
                        "y": [dfe.loc[dfe.Facility.eq(f), "Count"]],
                        "name": f,
                        "meta": f,
                    },
                ],
            }
            for f in ["Deworming needed", "Anemia"] # dfe["Facility"].unique()
        ],
        "direction": "down",
        "showactive": True,
    }
]

fig = fig.update_layout(updatemenus=updatemenus)

# px does not set an appropriate hovertemplate....
fig.update_traces(
    hovertemplate="Facility=%{meta}<br>Month=%{x}<br>Count=%{y}<extra></extra>",
    meta="Deworming needed",
)

Rob Raymond
  • 29,118
  • 3
  • 14
  • 30