I keep receiving callback error. I would like to know what's wrong here. Could you guys help?

So, here is the full code:

from dash import Dash, html, dcc, Input, Output, State
import dash_bootstrap_components as dbc
import plotly.express as px
import pandas as pd
import numpy as np

#================================================#

app = Dash(__name__, external_stylesheets= [dbc.themes.LUX])

df = pd.read_csv('df.csv')
df_fun = pd.read_csv('df_fun.csv')

#================================================#

fig = px.histogram(
            df,
            y= 'Categoria',
            color= 'Gênero',
            template= 'plotly_white',
            barmode= 'group',
            title= '<b>FORÇA DE TRABALHO POR GÊNERO</b>',
            category_orders= {
                'Categoria': [
                    'Membra/Membro',
                    'Analista',
                    'Técnica/Técnico',
                    'Pessoal sem vínculo',
                    'Requisitada/Requisitado',
                    'Estagiária/Estagiário'
                ],
                'Gênero': ['Mulheres', 'Homens']
            },
            hover_data= {
                'Gênero': False,
                'Categoria': False
            } 
        )

fig.update_layout(
            font_family= 'Bahnschrift',
            font_size= 13,
            xaxis_title= '',
            yaxis_title= '',
            height= 450,
            width= 900,
            legend_title= '',
            legend_x= 1,
            legend_y= 1.25,
            legend_xanchor= 'right',
            xaxis_dtick= 100,
            hoverlabel_font_color= 'white' 
        )

fig.update_traces(
            marker_line_width= 0.3,
            marker_line_color= 'black',
            hovertemplate= (
                'Total: %{x} <extra></extra>'
            )
        )

#================================================#

SIDEBAR_STYLE = {
    "position": "fixed",
    "top": 0,
    "left": 0,
    "bottom": 0,
    "width": "13rem",
    "padding": "2rem 1rem",
    "background-color": "lightgray",
    'color': 'black'
}

RIGHT_INFO_STYLE = {
    "margin-left": "6rem",
    "margin-right": "1rem",
    "padding": "2rem 1rem"
}

sidebar = html.Div(
    [
        html.H2("MPT", className="display-4", style= {'text-align':'center', 'color':'red'}),
        html.H3('Dashboard', style= {'text-align':'center', 'color':'brown'}),
        html.Hr(),
        html.P("Selecione abaixo as informações de interesse:", className="lead"),
        html.P('Composição', style= {'font-weight':'bold', 'text-decoration': 'underline'}),
        dcc.RadioItems(options=[
            {'label':'Força de Trabalho Total', 'value':'FT'},
            {'label':'Membras/Membros', 'value':'MM'},
            {'label':'Servidores', 'value':'S'}], value= 'FT', id= 'comp'),
        html.Hr(),
        html.P('Gratificação', style= {'font-weight':'bold', 'text-decoration': 'underline'}),
        dcc.RadioItems(options=[
            {'label':'Indiferente', 'value':'Ind'},
            {'label':'Com Função', 'value':'CF'},
            {'label':'Sem Função', 'value':'SF'}], value= 'Ind', id= 'grat'),
        html.Hr(),
        html.P('Informação', style= {'font-weight':'bold', 'text-decoration': 'underline'}),
        dcc.Checklist(options= ['Gênero', 'Cor/Raça', 'Faixa de Idade', 'Deficiência'], value= ['Gênero'], id= 'info'),
        html.Br(),
        dbc.Button('Gerar', id= 'button', n_clicks= 0)
    ],
    style= SIDEBAR_STYLE
)

app.layout = dbc.Container([sidebar, 
                            html.Div(dcc.Graph(id= 'graph', figure= fig), style= RIGHT_INFO_STYLE)])

#================================================#
@app.callback(
    Output('graph', 'figure'),
    State('comp', 'value'),
    State('grat', 'value'),
    State('info', 'value'),
    Input('button', 'n_clicks')
)
def FT_gênero(comp_value, grat_value, info_value):
    if grat_value == 'Indiferente' and info_value == 'Gênero' and comp_value == 'Força de Trabalho Total':
        fig = px.histogram(
            df,
            y= 'Categoria',
            color= 'Gênero',
            template= 'plotly_white',
            barmode= 'group',
            title= '<b>FORÇA DE TRABALHO POR GÊNERO</b>',
            category_orders= {
                'Categoria': [
                    'Membra/Membro',
                    'Analista',
                    'Técnica/Técnico',
                    'Pessoal sem vínculo',
                    'Requisitada/Requisitado',
                    'Estagiária/Estagiário'
                ],
                'Gênero': ['Mulheres', 'Homens']
            },
            hover_data= {
                'Gênero': False,
                'Categoria': False
            } 
        )

        fig.update_layout(
            font_family= 'Bahnschrift',
            font_size= 13,
            xaxis_title= '',
            yaxis_title= '',
            height= 450,
            width= 900,
            legend_title= '',
            legend_x= 1,
            legend_y= 1.25,
            legend_xanchor= 'right',
            xaxis_dtick= 100,
            hoverlabel_font_color= 'white' 
        )

        fig.update_traces(
            marker_line_width= 0.3,
            marker_line_color= 'black',
            hovertemplate= (
                'Total: %{x} <extra></extra>'
            )
        )

    elif grat_value == 'Com Função' and info_value == 'Gênero' and comp_value == 'Força de Trabalho Total':
        df = pd.DataFrame(
            df.loc[df['Identificado de Gratificacao'] == 'Com Função', :].groupby(
            ['Identificado de Gratificacao', 'Gênero'])['Gênero'].count().reset_index(name= 'Total')
        )
        fig = px.pie(
            df,
            values= 'Total',
            names= 'Gênero',
            template= 'plotly_white',
            title= '<b>FORÇA DE TRABALHO COM FUNÇÃO, POR GÊNERO</b>',
            category_orders= {'Gênero': ['Mulheres', 'Homens']},
            hover_data= {'Gênero': False} 
        )

        fig.update_layout(
            font_family= 'Bahnschrift',
            font_size= 13,
            height= 650,
            width= 900,
            legend_x= 1.18,
            legend_y= 0.8,
            legend_xanchor= 'right',
            hoverlabel_font_color = 'white'
        )

        fig.update_traces(
            pull= 0.04,
            textfont_color= 'white'
        )
    else:
        df = pd.DataFrame(
            df.loc[df['Identificado de Gratificacao'] == 'Sem Função', :].groupby(
            ['Identificado de Gratificacao', 'Gênero'])['Gênero'].count().reset_index(name= 'Total')
        )
        fig = px.pie(
            df,
            values= 'Total',
            names= 'Gênero',
            template= 'plotly_white',
            title= '<b>FORÇA DE TRABALHO SEM FUNÇÃO, POR GÊNERO</b>',
            category_orders= {'Gênero': ['Mulheres', 'Homens']},
            hover_data= {'Gênero': False} 
        )

        fig.update_layout(
            font_family= 'Bahnschrift',
            font_size= 13,
            height= 650,
            width= 900,
            legend_x= 1.18,
            legend_y= 0.8,
            legend_xanchor= 'right',
            hoverlabel_font_color = 'white'
        )

        fig.update_traces(
            pull= 0.04,
            textfont_color= 'white'
        )
    return fig

#=================================================#

if __name__ == '__main__':
    app.run_server(debug= True)

What might be wrong there? The callback error keeps appearing…

It’s hard to know for sure because there is no sample data and I can’t run your app, but it’s likely that you are missing a variable in the callback function. There are 4 inputs - 3 States for the RadioItems and Checklist, and 1 Input for the Button, but only 3 variables

app.callback(
    Output('graph', 'figure'),
    State('comp', 'value'),
    State('grat', 'value'),
    State('info', 'value'),
    Input('button', 'n_clicks')
)
def FT_gênero(comp_value, grat_value, info_value):


Try changing the function to:

def FT_gênero(comp_value, grat_value, info_value, n):

If that doesn’t fix the issue, please share the error message and some sample data :slight_smile:

1 Like

Hi, thanks for your help. I’ve check that and actually I did put another parameter into the function. I posted here the old version of the code. Here it is how the function is actually structured:

@app.callback(
    Output('graph', 'figure'),
    Input('button', 'n_clicks'),
    State('comp', 'value'),
    State('grat', 'value'),
    State('info', 'value')   
)
def FT_gênero(n_clicks, comp_value, grat_value, info_value):
    global df
    if grat_value == 'Indiferente' and info_value == 'gen' and comp_value == 'Força de Trabalho Total':
        fig = px.histogram(
            df,
            y= 'Categoria',
            color= 'Gênero',
            template= 'plotly_white',
            barmode= 'group',
            title= '<b>FORÇA DE TRABALHO POR GÊNERO</b>',
            category_orders= {
                'Categoria': [
                    'Membra/Membro',
                    'Analista',
                    'Técnica/Técnico',
                    'Pessoal sem vínculo',
                    'Requisitada/Requisitado',
                    'Estagiária/Estagiário'
                ],
                'Gênero': ['Mulheres', 'Homens']
            },
            hover_data= {
                'Gênero': False,
                'Categoria': False
            } 
        )

        fig.update_layout(
            font_family= 'Bahnschrift',
            font_size= 13,
            xaxis_title= '',
            yaxis_title= '',
            height= 450,
            width= 900,
            legend_title= '',
            legend_x= 1,
            legend_y= 1.25,
            legend_xanchor= 'right',
            xaxis_dtick= 100,
            hoverlabel_font_color= 'white' 
        )

        fig.update_traces(
            marker_line_width= 0.3,
            marker_line_color= 'black',
            hovertemplate= (
                'Total: %{x} <extra></extra>'
            )
        )

    elif grat_value == 'Com Função' and info_value == 'Gênero' and comp_value == 'Força de Trabalho Total':
        df = pd.DataFrame(
            df.loc[df['Identificado de Gratificacao'] == 'Com Função', :].groupby(
            ['Identificado de Gratificacao', 'Gênero'])['Gênero'].count().reset_index(name= 'Total')
        )
        fig = px.pie(
            df,
            values= 'Total',
            names= 'Gênero',
            template= 'plotly_white',
            title= '<b>FORÇA DE TRABALHO COM FUNÇÃO, POR GÊNERO</b>',
            category_orders= {'Gênero': ['Mulheres', 'Homens']},
            hover_data= {'Gênero': False} 
        )

        fig.update_layout(
            font_family= 'Bahnschrift',
            font_size= 13,
            height= 650,
            width= 900,
            legend_x= 1.18,
            legend_y= 0.8,
            legend_xanchor= 'right',
            hoverlabel_font_color = 'white'
        )

        fig.update_traces(
            pull= 0.04,
            textfont_color= 'white'
        )
    else:
        df = pd.DataFrame(
            df.loc[df['Identificado de Gratificacao'] == 'Sem Função', :].groupby(
            ['Identificado de Gratificacao', 'Gênero'])['Gênero'].count().reset_index(name= 'Total')
        )
        fig = px.pie(
            df,
            values= 'Total',
            names= 'Gênero',
            template= 'plotly_white',
            title= '<b>FORÇA DE TRABALHO SEM FUNÇÃO, POR GÊNERO</b>',
            category_orders= {'Gênero': ['Mulheres', 'Homens']},
            hover_data= {'Gênero': False} 
        )

        fig.update_layout(
            font_family= 'Bahnschrift',
            font_size= 13,
            height= 650,
            width= 900,
            legend_x= 1.18,
            legend_y= 0.8,
            legend_xanchor= 'right',
            hoverlabel_font_color = 'white'
        )

        fig.update_traces(
            pull= 0.04,
            textfont_color= 'white'
        )
    return fig

And the problem persists. I’ll share more information:

As matter of fact I’m not receiving callback error anymore. The figure that starts the page are the last figure inside the function (the plot called “FORÇA DE TRABALHO SEM FUNÇÃO, POR GÊNERO”) however the radioitems and checklist doesn’t match the figure. They start correctly accordingnaly to its values set in app.layout(sidebar) but the corresponding plot are not correct. When I try to change te RadioItems and Checklist nothing happens with the figure. Everything remains the same. Here it is:

On the image bellow is the df.head(). The DataFrame I’m using.

Hi @rlarango

Please see Why Global Variables Will Break Your App

Yeah! I saw an hour ago that It’s not a good habit keeping global variables inside functions. I managed to make a copy. However, I’ve finally found the reason things weren’t working out! The parameter inside the function regarding the Checklist was being passed into the condition as a simple string, although it should be inside brackets because this dcc’s value is fulfilled with a list of strings after all! Thank you for your help!