尝试添加下拉列表以显示饼图时,plotly dash 仪表板上的回调错误

Callback error on plotly dash dashboard when trying to add a dropdown to show pie charts

我对 dash 还很陌生,但我正在尝试组装一个数据仪表板。我想要的是一个下拉列表,它基于输入呈现两个饼图之一。构造饼图的逻辑包含在我的回调函数中。它说它期待 1 个输出但它有两个。我在网上看过并尝试了不同的建议。我想我已经非常接近让它工作了,只是有些愚蠢的事情我没有做。

我知道这里的人都是巫师,所以我希望有人能帮助我。另外,如果有人精通 Dash,你能给我指出良好文档的方向,以了解如何定位它,这样我就可以更改布局,使这些图更适合仪表板,而不仅仅是网页吗?

太有爱了

谢谢

import pandas as pd
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
from jupyter_dash import JupyterDash
import plotly.graph_objects as go
import plotly.express as px
from dash import no_update
import plotly.figure_factory as ff



app = dash.Dash(__name__)

df = pd.read_csv('nyc-jobs.csv')
#top job categories
counts = df['Job Category'].value_counts()
counts = pd.DataFrame(counts)
counts = counts.head(10)
counts.sort_values(['Job Category'],ascending=True, inplace = True)

fig = px.bar(df, y=counts.index, x=counts['Job Category'])

#Salary range distribution
salary_counts = df['Salary Range To'].value_counts()
salary_counts = pd.DataFrame(counts)
group_labels = ['Salary Range From','Salary Range To']
fig3 = ff.create_distplot([df['Salary Range From'],df['Salary Range To']], group_labels, bin_size= 10000)


fig4 = go.Figure()
fig4.add_trace(go.Box(y=df['Salary Range From'], name='Salary Range From',
                marker_color = 'indianred'))
fig4.add_trace(go.Box(y=df['Salary Range To'], name = 'Salary Range To',
                marker_color = 'lightseagreen'))

# # of positions
df.sort_values(by = ['# Of Positions'], ascending = True, inplace = True)
df_group = df.groupby(['Business Title']).mean(['# Of Positions'])
df_group.sort_values('# Of Positions', ascending = True, inplace = True)
df_group.index = df_group.index.str.capitalize()

fig5 = px.bar(df, y=df_group.index[-5:], x=df_group['# Of Positions'][-5:])


app.layout = html.Div([
    html.H1("New York City Job Postings", style = {'text-align': 'center', 'font-family': 'Helvetica'}),
    
    #Job postings graph
    dcc.Graph(
        id='Top Job Postings',
        figure=fig
    ),
    html.Div([html.H2('Report Type:', style={'margin-right': '2em', 'font-family': 'Helvetica'}),]),
    dcc.Dropdown(id='input-type', 
                   options=[
                           {'label': 'Full vs part time report ', 'value': 'OPT1'},
                           {'label': 'Posting type', 'value': 'OPT2'}
                           ],
                  placeholder='Select a report type',
                  multi=False,
                  clearable=False,
                  style={'width':800, 'padding':3, 'font-size':20, 'text-align-last':'center', 'font-family': 'Helvetica'}),

    html.Div(id='output_container', children=[]),

    html.Div(dcc.Graph(id='pie_chart_reports')),


    #Salary Distributions
    dcc.Graph(
        id="Salary Distribution",
        figure = fig3),

    dcc.Graph(
        id="Salary Distribution boxplot",
        figure = fig4),

    dcc.Graph(
        id='Highest number of positions',
        figure=fig5
    )
])

@app.callback(
    [Output(component_id='pie_chart_reports', component_property='figure')],
    [Input(component_id='input-type', component_property='value')]
)

def update_graph(report_type):
    dff = df
    container = "The chosen report was: {}".format(report_type)
    
    if report_type == 'OPT1':
        #full time vs part time
        ft_pt = dff['Full-Time/Part-Time indicator']
        ft_pt.fillna('Not listed', inplace = True)
        ft_pt.replace('F', 'Full Time', inplace = True)
        ft_pt.replace('P', 'Part Time', inplace = True)
        value_counts_ft_pt = dff['Full-Time/Part-Time indicator'].value_counts()
        labels_ft_pt = value_counts_ft_pt.index.tolist()

        fig1 = px.pie(dff, 
        values = value_counts_ft_pt, 
        names = labels_ft_pt)

        return container, dcc.Graph(id='pie_chart_reports',figure=fig1)

    else:
        #internal vs externl
        value_counts_posting_type = dff['Posting Type'].value_counts()
        labels_posting_type = value_counts_posting_type.index.tolist()
        fig2 = px.pie(
            df, 
            values = value_counts_posting_type, 
            names = labels_posting_type, 
            color_discrete_sequence=px.colors.sequential.Bluyl)
        
        return container, dcc.Graph(id='pie_chart_reports',figure=fig2)


    

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

第一个问题是你的回调有一个输出,但是你 return 一个包含两个东西的元组。因此,您可以添加一个 Output 来定位您希望其值为 content 的元素,我猜该元素是 ID 为 output_container 的元素。另一种选择是从 return 语句中删除 content

第二个问题是 Output 被列表包围,因此 dash 期望 return 值是一个包含一个值的列表。您可以删除 Ouput 周围的列表,因此它需要一个元组

Output(component_id='pie_chart_reports', component_property='figure')

或者您可以用列表包围您的 return 值。

第三个问题是您的目标是 component_property figure,但您 return 是 Graph 组件。例如,您应该 return fig1 而不是 dcc.Graph(id='pie_chart_reports', figure=fig1)