Ben
Ben

Reputation: 193

Plotly Dash: How to prevent Figure from appearing when no dropdown value is selected?

I'm building a dashboard (code below) and my goal is to show several key facts about the data on a country-level basis. For example, current population vs. average population of all countries, life expectation vs. average life expectation of all countries etc.

I don't want to display the graph when no country (i.e. no dropdown option) is selected. This should also be standard when first launching the dashboard. However, I receive an error message when either clearing the dropdown or setting the value to '' in the layout area.

Does anybody know any solution to this problem?

import pandas as pd
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')

fig = go.Figure()

# create the Dash app
app = dash.Dash()

# set up app layout
app.layout = html.Div(children=[
    html.H1(children='Demographic Statistics'),
    dcc.Dropdown(id='country-dropdown',
                options=[{'label': x, 'value': x}
                        for x in df.country.unique()],
                  value='Argentina',
                 multi=False, clearable=True),
    dcc.Graph(id='indicators',  figure=fig)
])

# set up the callback function
@app.callback(
    Output('indicators', 'figure'),
    [Input('country-dropdown', 'value')])

def display_demographic_statistics(selected_country):
    filtered_country = df[df.country == selected_country]  
     
    pop_confirmed = df.loc[df['country'] == selected_country, 'pop'].iloc[0]
    lifexp = df.loc[df['country'] == selected_country, 'lifeExp'].iloc[0]
    average_confirmed = df["pop"].mean()
    average_lifexp = df["lifeExp"].mean()
    return {
            'data': [go.Indicator(
                    mode='number+delta',
                    value=pop_confirmed,
                    delta={'reference': average_confirmed,
                              'position': 'right',
                              'valueformat': ',g',
                              'relative': False,

                              'font': {'size': 15}},
                    number={'valueformat': ',',
                            'font': {'size': 20},

                               },
                    domain={'y': [0, 1], 'x': [0, 1]})],

            'layout': go.Layout(
                 title={'text': 'Demgraphic Statistics'},
                grid = {'rows': 2, 'columns': 2, 'pattern': "independent"},
                template = {'data' : {'indicator': [{
                'mode' : "number+delta+gauge",
                'delta' : {'reference': 90}}]}}
            ),
    }

# Run local server
if __name__ == '__main__':
    app.run_server(debug=True, use_reloader=False)

Upvotes: 0

Views: 1541

Answers (1)

user11989081
user11989081

Reputation: 8654

You could make the component with id='indicators' an html.Div and use the callback to update its children property as follows:

  • if the user selects a country from the dropdown, then the callback returns a dcc.Graph with the indicators for the selected country,
  • if the user clears the dropdown, then the callback returns None (i.e. nothing).

Note also that the value of the dropdown when no selection has been made is None, not ''.

import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import pandas as pd

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')

app = dash.Dash()

app.layout = html.Div(children=[

    html.H1(children='Demographic Statistics'),

    dcc.Dropdown(
        id='country-dropdown',
        options=[{'label': x, 'value': x} for x in df.country.unique()],
        value=None,
        multi=False,
        clearable=True
    ),

    html.Div(id='indicators')

])

@app.callback(
    Output('indicators', 'children'),
    [Input('country-dropdown', 'value')])
def display_demographic_statistics(selected_country):

    if selected_country is not None:

        pop_confirmed = df.loc[df['country'] == selected_country, 'pop'].iloc[0]
        average_confirmed = df['pop'].mean()

        return dcc.Graph(
            figure=go.Figure(
                data=go.Indicator(
                    mode='number+delta',
                    value=pop_confirmed,
                    delta={
                        'reference': average_confirmed,
                        'position': 'right',
                        'valueformat': ',g',
                        'relative': False,
                        'font': {'size': 15}
                    },
                    number={
                        'valueformat': ',',
                        'font': {'size': 20},
                    },
                    domain={
                        'y': [0, 1],
                        'x': [0, 1]
                    }
                ),
                layout=go.Layout(
                    title={'text': 'Demgraphic Statistics'},
                    grid={'rows': 2, 'columns': 2, 'pattern': 'independent'},
                    template={'data': {'indicator': [{'mode': 'number+delta+gauge', 'delta': {'reference': 90}}]}}
                )
            )
        )

    else:

        return None

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

Upvotes: 3

Related Questions