Add Update Menus to Plotly Figure without getting TypeError

Hello All -

New to the Forum / Plotly /Python so please excuse / point out any errors.
I’m currently experimenting with a basic idea of having a single plotly figure showing a single graph, but with a series of buttons which when clicked, will change the underlying data of the graph.
I’m copied my formatting from official plotly sites, although I haven’t seen the “data_frame” arg of a plot changed before in any of the examples I’ve seen.
See my code below ( “statedatahalfed.csv” is a simple table with “state” the State Name and “loss” a float.

df = pd.read_csv("statedatahalfed.csv")
import plotly.express as px

top10lossstates = df.sort_values('loss',ascending = False)[:10]
top5lossstates = df.sort_values('loss',ascending = False)[:5]
bot10lossstates = df.sort_values('loss',ascending = True)[:10]

optbuttons = [
    {'label': "Top 10", 'method': 'update', 'args': [{'data_frame': top10lossstates },{'title': 'Top 10 States'}]},
    {'label': "Top 5", 'method': 'update', 'args': [{'data_frame': top5lossstates },{'title': 'Top 5 States'}]},
    {'label': "Bottom 10", 'method': 'update', 'args': [{'data_frame': bot10lossstates },{'title': 'Bottom 10 States'}]}
]

piechart = px.pie(data,values = 'loss',names = 'state')

piechart.update_layout(
    {
        'updatemenus':[
            {
                'type':'buttons',
                'direction':'down',
                'x':0.8,
                'y':0.8,
                'buttons': optbuttons
            }
        ]
    }
)

piechart.show()

When I run this code I get a TypeError : Object of type DataFrame is not JSON serializable. If I comment out the piechart.update_layout line then it runs fine.

Can anyone point out the issue here? Is it simply that the underlying dataframe is not an argument which can be changed by a button? Would I have to instead plot all three piecharts, hide two of them, and then have the buttons update which is hidden?

Thanks

hi @Ehard
:wave: Welcome to the community.

Can you share the statedatahalfed dataset with us so we can run and reproduce your code on our computers?

Hi @adamschroeder
Thanks for the reply.
I couldn’t get the file directly attached but hopefully you’re able to convert this back into csv

code,state,loss,tolerance
AL,Alabama,105.5,150
AK,Alaska,144,150
AZ,Arizona,35.5,170
AR,Arkansas,78,140
CA,California,145.5,160
CO,Colorado,85.5,170
CT,Connecticut,131.5,170
DE,Delaware,112.5,190
FL,Florida,91.5,170
GA,Georgia,134.5,160
HI,Hawaii,43,190
ID,Idaho,86,190
IL,Illinois,93.5,120
IN,Indiana,112.5,190
IA,Iowa,124.5,110
KS,Kansas,137.5,130
KY,Kentucky,138.5,140
LA,Louisiana,146,120
ME,Maine,131.5,170
MD,Maryland,65.5,160
MA,Massachusetts,149.5,150
MI,Michigan,46.5,130
MN,Minnesota,125.5,110
MS,Mississippi,53.5,200
MO,Missouri,75,160
MT,Montana,93,120
NE,Nebraska,127.5,160
NV,Nevada,72,190
NH,New Hampshire,123,140
NJ,New Jersey,37,140
NM,New Mexico,107,200
NY,New York,42,160
NC,North Carolina,73.5,150
ND,North Dakota,83,130
OH,Ohio,34,140
OK,Oklahoma,72.5,110
OR,Oregon,99,140
PA,Pennsylvania,139.5,120
RI,Rhode Island,116.5,180
SC,South Carolina,67,150
SD,South Dakota,134.5,190
TN,Tennessee,51,110
TX,Texas,34,
UT,Utah,78,160
VT,Vermont,29,120
VA,Virginia,137,130
WA,Washington,136,120
WV,West Virginia,124,120
WI,Wisconsin,68.5,150
WY,Wyoming,79,110

hi @Ehard
I’m getting weird errors with your code. I just DM’d you so we can try to solve this together. When we’re done, you can post the solution here.

hi @Ehard
to solve this issue you need to modify the args of the buttons. Instead of assigning a complete dataframe, you need to assign the columns that pertain to the values and names attribute of a pie chart.

optbuttons = [
    {'label': "Top 10", 'method': 'update', 'args': [{'values': [top10lossstates['loss']], 'names': [top10lossstates['state']]},{'title': 'Top 10 States'}]},
    {'label': "Top 5", 'method': 'update', 'args': [{'values': [top5lossstates['loss']], 'names': [top5lossstates['state']]},{'title': 'Top 5 States'}]},
    {'label': "Bottom 10", 'method': 'update', 'args': [{'values': [bot10lossstates['loss']], 'names': [bot10lossstates['state']]},{'title': 'Bottom 10 States'}]}
]

This complete code should work:

import plotly.express as px
import pandas as pd


df = pd.read_csv("statedatahalfed.csv")

top10lossstates = df.sort_values('loss',ascending = False)[:10]
top5lossstates = df.sort_values('loss',ascending = False)[:5]
bot10lossstates = df.sort_values('loss',ascending = True)[:10]

optbuttons = [
    {'label': "Top 10", 'method': 'update', 'args': [{'values': [top10lossstates['loss']], 'names': [top10lossstates['state']]},{'title': 'Top 10 States'}]},
    {'label': "Top 5", 'method': 'update', 'args': [{'values': [top5lossstates['loss']], 'names': [top5lossstates['state']]},{'title': 'Top 5 States'}]},
    {'label': "Bottom 10", 'method': 'update', 'args': [{'values': [bot10lossstates['loss']], 'names': [bot10lossstates['state']]},{'title': 'Bottom 10 States'}]}
]

piechart = px.pie(df,values = 'loss',names = 'state')

piechart.update_layout(
updatemenus=[
        dict(
            type = "buttons",
            direction = "down",
            buttons=optbuttons,
            x=0.8,
            xanchor="left",
            y=0.8,
            yanchor="top"
        ),
    ]
)

piechart.show()
1 Like

That worked great - thank you Adam! Do you know why the data_frame arg can’t be changed in the same way as the values or names? Or is it just something to remember and work around in the future

1 Like