Plotly Dash:如何在未选择下拉值时防止 Figure 出现?

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

我正在构建一个仪表板(下面的代码),我的目标是显示有关国家/地区数据的几个关键事实。例如,当前人口与各国平均人口,预期寿命与各国平均预期寿命等

我不想在没有选择国家(即没有下拉选项)时显示图表。首次启动仪表板时,这也应该是标准的。但是,在布局区域中清除下拉列表或将值设置为 '' 时,我收到一条错误消息。

有人知道这个问题的解决方案吗?

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)

您可以使用 id='indicators' 使组件成为 html.Div 并使用回调更新其 children 属性 如下:

  • 如果用户从下拉列表中选择一个国家,则回调 returns a dcc.Graph 包含所选国家/地区的指标,
  • 如果用户清除下拉菜单,则回调 returns None(即什么都没有)。

另请注意,未进行选择时下拉列表的值为 None,而不是 ''

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)