Use updatemenus to switch between 2 data frames

Hello, I need some help!

I’m trying to use updatemenus to switch between 2 data frames, but only the title is changing. Could you help me, please?

import plotly.express as px
import pandas as pd

Criando o primeiro data frame

df1 = pd.DataFrame({
‘Mês’: [‘Jan’, ‘Fev’, ‘Mar’, ‘Abr’, ‘Mai’, ‘Jun’, ‘Jul’, ‘Ago’, ‘Set’, ‘Out’, ‘Nov’, ‘Dez’],
‘Vendas’: [10000, 20000, 15000, 17000, 16000, 19000, 21000, 22000, 23000, 25000, 26000, 27000]
})

Criando o segundo data frame

df2 = pd.DataFrame({
‘Mês’: [‘Jan’, ‘Fev’, ‘Mar’, ‘Abr’, ‘Mai’, ‘Jun’, ‘Jul’, ‘Ago’, ‘Set’, ‘Out’, ‘Nov’, ‘Dez’],
‘Vendas’: [12000, 22000, 17000, 19000, 18000, 21000, 23000, 24000, 25000, 27000, 28000, 29000]
})

Criando o gráfico de linha

fig = px.line(df1, x=‘Mês’, y=‘Vendas’, title=‘Vendas por Mês’)

Adicionando os botões para mudar a fonte de dados

buttons = [
dict(label=‘Vendas - DF1’, method=‘update’, args=[
{‘data’: [dict(x=df1[‘Mês’], y=df1[‘Vendas’])]},
{‘title’: ‘Vendas por Mês - DF1’}
]),
dict(label=‘Vendas - DF2’, method=‘update’, args=[
{‘data’: [dict(x=df2[‘Mês’], y=df2[‘Vendas’])]},
{‘title’: ‘Vendas por Mês - DF2’}
]),
]

fig.update_layout(updatemenus=[
dict(active=0, buttons=buttons)
])

fig.show()

Hi @Kleber welcome to the forums.

Could you please format your code for better readability?

import plotly.express as px
import pandas as pd

df1 = pd.DataFrame({
‘Mês’: [‘Jan’, ‘Fev’, ‘Mar’, ‘Abr’, ‘Mai’, ‘Jun’, ‘Jul’, ‘Ago’, ‘Set’, ‘Out’, ‘Nov’, ‘Dez’],
‘Vendas’: [10000, 20000, 15000, 17000, 16000, 19000, 21000, 22000, 23000, 25000, 26000, 27000]
})

df2 = pd.DataFrame({
‘Mês’: [‘Jan’, ‘Fev’, ‘Mar’, ‘Abr’, ‘Mai’, ‘Jun’, ‘Jul’, ‘Ago’, ‘Set’, ‘Out’, ‘Nov’, ‘Dez’],
‘Vendas’: [12000, 22000, 17000, 19000, 18000, 21000, 23000, 24000, 25000, 27000, 28000, 29000]
})

fig = px.line(df1, x=‘Mês’, y=‘Vendas’, title=‘Vendas por Mês’)

buttons = [
dict(label=‘Vendas - DF1’, method=‘update’, args=[
{‘data’: [dict(x=df1[‘Mês’], y=df1[‘Vendas’])]},
{‘title’: ‘Vendas por Mês - DF1’}
]),
dict(label=‘Vendas - DF2’, method=‘update’, args=[
{‘data’: [dict(x=df2[‘Mês’], y=df2[‘Vendas’])]},
{‘title’: ‘Vendas por Mês - DF2’}
]),
]

fig.update_layout(updatemenus=[
dict(active=0, buttons=buttons)
])

fig.show()

@Kleber
Your button definition is incomplete. This is the code that works:

import plotly.express as px
import pandas as pd
import plotly.graph_objects as go
df1 = pd.DataFrame({'Mes': ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
'Vendas': [10000, 20000, 15000, 17000, 16000, 19000, 21000, 22000, 23000, 25000, 26000, 27000]
})

df2 = pd.DataFrame({
'Mes': ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
'Vendas': [12000, 22000, 17000, 19000, 18000, 21000, 23000, 24000, 25000, 27000, 28000, 29000]
})

fig = px.line(df1, x='Mes', y='Vendas', title='Vendas por Mes')

buttons = [
      dict(label='Vendas - DF1', 
           method='restyle', 
           args=[{'x': [df1['Mes']], 'y': [df1['Vendas']]},
                 {'title':' Vendas por Mes - DF1'}
                
           ]),
      dict(label='Vendas - DF2', 
           method='update', 
           args=[{'x':[df2['Mes']], 'y': [df2['Vendas']], },
                 {'title':'Vendas por Mes - DF1'}
          ]),
       ]

fig.update_layout(updatemenus=[dict(active=0, buttons=buttons)],
                  yaxis_range=[9800, 29800])

fig.show()

fig.data is a list of traces. Here it is a list with a single element. That’s why when the button args are defined you must set:

x = [df1['Mes`]], y= [df1['Vendas']
x = [df2['Mes`]], y= [df2['Vendas']

The outermost [ ], point out that x, and y are updated in the unique trace defined initially in fig.data =[go.Scatter(...)]

@empet
Show!
Just one more help, I’ll need to include a column with some categories, about 5 categories under the variable “Categoria”, in this example I only put 2 (A, B) and made the adjustment in the code including the “color” parameter, but when I switch between data frames the graph looks strange, as if the “color” parameter was not activated, can you help me?

import plotly.express as px
import pandas as pd
import plotly.graph_objects as go

df1 = pd.DataFrame({
'Mes': ['Jan', 'Jan', 'Fev','Fev', 'Mar','Mar', 'Abr', 'Abr','Mai','Mai', 'Jun', 'Jun'],
'Categoria': ['A', 'B', 'A', 'B', 'A','B','A','B', 'A','B', 'A','B'],
'Vendas': [10000, 20000, 15000, 17000, 16000, 19000, 21000, 22000, 23000, 25000, 26000, 27000]
})

df2 = pd.DataFrame({
'Mes': ['Jan', 'Jan', 'Fev','Fev', 'Mar','Mar', 'Abr', 'Abr','Mai','Mai', 'Jun', 'Jun'],
'Categoria': ['A', 'B', 'A', 'B', 'A','B','A','B', 'A','B', 'A','B'],
'Vendas': [12000, 22000, 17000, 19000, 18000, 21000, 23000, 24000, 25000, 27000, 28000, 29000]
})

fig = px.line(df1, x='Mes', y='Vendas', title='Vendas por Mes', color='Categoria',text= 'Vendas')

buttons = [
      dict(label='Vendas - DF1', 
           method='restyle', 
           args=[{'x': [df1['Mes']], 'y': [df1['Vendas']], 'color': [df1['Categoria']]},
                 {'title':' Vendas por Mes - DF1'}
                
           ]),
      dict(label='Vendas - DF2', 
           method='update', 
           args=[{'x':[df2['Mes']], 'y': [df2['Vendas']], 'color': [df2['Categoria']]},
                 {'title':'Vendas por Mes - DF1'}
          ]),
       ]

fig.update_layout(updatemenus=[dict(active=0, buttons=buttons)],
                  yaxis_range=[9800, 29800]
                  )

fig.show()

For the initial data:
from your posted code, your px.line draws a single line that can have a unique color, set by fig.update_traces(line_color="blue").
Each button updates x, y data for that line. To change the line color, you must add to the first button arg dict, "line.color": ["blue"], respectively "line.color": ["red"], to the second one.

Note, that in the button definition we do not write line_color="blue", because plotly.js does not understand that line_color, representing line=dict(color), is a nested dict. For javascript we must pass it as "line.color": ["blue"].

Code for initial data, with updating line color by each button:

import plotly.express as px
import pandas as pd
import plotly.graph_objects as go
df1 = pd.DataFrame({'Mes': ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
'Vendas': [10000, 20000, 15000, 17000, 16000, 19000, 21000, 22000, 23000, 25000, 26000, 27000]
})

df2 = pd.DataFrame({
'Mes': ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
'Vendas': [12000, 22000, 17000, 19000, 18000, 21000, 23000, 24000, 25000, 27000, 28000, 29000]
})

fig = px.line(df1, x='Mes', y='Vendas', title='Vendas por Mes')
fig.update_traces(line_color="magenta")


buttons = [
      dict(label='Vendas - DF1', 
           method='restyle', 
           args=[{'x':[df1['Mes']], 'y':[df1['Vendas']], 'line.color':['magenta']},
                  {'title':'Vendas por Mes - DF1'}
                
           ]),
      dict(label='Vendas - DF2', 
           method='update', 
           args=[{'x':[df2['Mes']], 'y': [df2['Vendas']], 'line.color':['red']},
                  {'title':'Vendas por Mes - DF1'}
          ]),
       ]

fig.update_layout(updatemenus=[dict(active=0, buttons=buttons),
                              ],
                 yaxis_range=[9800, 29800])

When you define a new column, Categoria, then fig=px_line() contains as many traces as categories.
VERY IMPORTANT!!! In button definition you have to use exclusively attributes of go.TraceName. updatemenus is not aware of arguments in px.function(s). That’s why you got something unexpected when in button definition included ‘color’: df1['Categoria`].
In this case you have to groupby your dataframes by categories:

df1 = pd.DataFrame({
'Mes': ['Jan', 'Jan', 'Fev','Fev', 'Mar','Mar', 'Abr', 'Abr','Mai','Mai', 'Jun', 'Jun'],
'Categoria': ['A', 'B', 'A', 'B', 'A','B','A','B', 'A','B', 'A','B'],
'Vendas': [10000, 20000, 15000, 17000, 16000, 19000, 21000, 22000, 23000, 25000, 26000, 27000]
})

df2 = pd.DataFrame({
'Mes': ['Jan', 'Jan', 'Fev','Fev', 'Mar','Mar', 'Abr', 'Abr','Mai','Mai', 'Jun', 'Jun'],
'Categoria': ['A', 'B', 'A', 'B', 'A','B','A','B', 'A','B', 'A','B'],
'Vendas': [12000, 22000, 17000, 19000, 18000, 21000, 23000, 24000, 25000, 27000, 28000, 29000]
})

fig = px.line(df1, x='Mes', y='Vendas', title='Vendas por Mes', color='Categoria',text= 'Vendas')

dg1=df1.groupby(['Categoria']).get_group('A')
dg2=df1.groupby(['Categoria']).get_group('B')
dh1=df2.groupby(['Categoria']).get_group('A')
dh2=df2.groupby(['Categoria']).get_group('B')

buttons = [
      dict(label='Vendas - DF1', 
           method='restyle', 
           args=[{'x': [dg1['Mes'], dg2['Mes']], 'y': [dg1['Vendas'], dg2['Vendas']], 'line.color': ['#636efa', 'c0c0c0']},
                 {'title':' Vendas por Mes - DF1'}
                
           ]),
      dict(label='Vendas - DF2', 
           method='update', 
           args=[{'x':[dh1['Mes'], dh2['Mes']], 'y': [dh1['Vendas'], dh2['Vendas']], 'line.color': ['#EF553B', '#ffd700']},
                 {'title':'Vendas por Mes - DF1'}
          ]),
       ]

fig.update_layout(updatemenus=[dict(active=0, buttons=buttons)],
                  yaxis_range=[9800, 29800]
                  )

Show!
Thank you very much!