仪表板上出现错误 'An object was provided as `children` instead of a component....'

Error 'An object was provided as `children` instead of a component....' appears on dashboard

示例 csv 数据:

date,Data Center,Customer,companyID,source,target,value 6/1/2021,dcA,customer1,companyID1,step1:open_list_view,exit,1 6/1/2021,dcB,customer2,companyID2,step1:open_list_view,exit,1 6/1/2021,dcC,customer3,companyID3,step1:open_list_view,exit,1 6/2/2021,dcD,customer4,companyID4,step1:open_list_view,exit,2 6/2/2021,dcE,customer5,companyID5,step1:open_list_view,step2:switch_display_option,1

我 运行 下面的代码用于将桑基图放在仪表板中,并且可以通过应用过滤器相应地更新图表。但仪表板上出现错误。有什么问题?

An object was provided as children instead of a component, string, or number (or list of those). Check the children property that looks something like:

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

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}

dataset = pd.read_csv('perfGoal_cleanSankey.csv')

labelListTemp1 = list(set(dataset.source.values))
labelListTemp2 = list(set(dataset.target.values))
labelList = labelListTemp1 + labelListTemp2
sankey_node = list(dict.fromkeys(labelList))
 
fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=20,line = dict(color = "black", width = 0.5),label = labelList,color = 'black' ),
                                 link = dict(source = dataset.source.apply(lambda x: labelList.index(x)),
                                             target = dataset.target.apply(lambda x: labelList.index(x)),
                                             value = dataset.value))])

#fig.update_layout(autosize=False,width = 3000,height = 1000,hovermode = 'x',title="performance Goal user behavior monitor",font=dict(size=16, color='blue'))
    
#fig.write_html('/Users/i073341/Desktop/plotly/perfUXRGoal.html', auto_open=True)
#fig.show()



app.layout = html.Div([
    dcc.Dropdown(
        id='dataCenter_dropdown',
        options=[ {'label': i, 'value': i} for i in dataset['Data Center'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Data Center'),
    dcc.Dropdown(
        id='customer_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['Customer'].unique()]  + [{'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Customer'),
    
    dcc.Dropdown(
        id='companyID_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['companyID'].unique()] + [{'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select companyID'),
    
    
#    html.Div(id='dd-output-container'),
     dcc.Graph(id='uxrPerfGoalSankey',figure=fig)
])

@app.callback(
#    Output('dd-output-container', 'children'),
    Output('uxrPerfGoalSankey', 'figure'),
    [Input('dataCenter_dropdown', 'value'),
     Input('customer_dropdown', 'value'),
     Input('companyID_dropdown', 'value')])


def update_graph(dataCenter, customer, companyID):

    if dataCenter=='Select all' and customer=='Select all' and companyID=='Select all':
        df=dataset.copy()
    else:
        df = dataset.loc[dataset['Data Center'].isin([dataCenter]) & dataset['Customer'].isin([customer]) & dataset['companyID'].isin([companyID])]
    
    labelListTemp1 = list(set(df.source.values))
    labelListTemp2 = list(set(df.target.values))
    labelList = labelListTemp1 + labelListTemp2
    sankey_node = list(dict.fromkeys(labelList))
    
    fig = go.Figure(data=[go.Sankey( node = dict( pad=15,thickness=20,line = dict(color = "black", width = 0.5),label = labelList,color = "blue" ),
                                     link = dict(source = df.source.apply(lambda x: labelList.index(x)),
                                                 target = df.target.apply(lambda x: labelList.index(x)),
                                                 value = df.value))])
    return fig
    
    

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

您的回调函数 return 是一个 figure 并且正在尝试将其分配给 html.Divchildren 属性。据我所知不能那样做。 div 的子项应该是错误消息中所述的其他组件、字符串或数字。

你是想写吗

Output('uxrPerfGoalSankey', 'figure'),

代替?

如果没有,你需要 return 一个新的无花果到那个 div,在你的 div 和 return 里面创建一个 dcc.Graph 这个图形的图形取而代之的价值。

编辑:

您还可以在回调函数的顶部覆盖您的输入值。不管你 select 是什么,df 最终都会被相同的值过滤。 IE。您在下拉列表中 select dataCenter 'A' 但在第一行中将 dataCenter 设置为 dataframe['Data Center'],那么 selecting one 的意义何在?如果不是故意的,请删除这些分配?

顺便说一句,一个迫在眉睫的陷阱:多下拉菜单传递 单个值 值列表。为了使你的 df selection 一致,强制所有输入为列表:

if not isinstance(dataCenter, list):
    dataCenter = [dataCenter]
# etc

编辑 2:

问题在于您如何处理列表参数与单个值以及 'select all' 的 selection。我调整了逻辑以将 'None'(dd selection 为空)和 'Select all' 视为所有值 selected。如果您不想在 selection 为空时绘制任何内容,请改为执行此操作:

from dash.exceptions import PreventUpdate

...

然后在你的回调函数中做第一件事:

if dataCenter is None or customer is None or companyID is None:
    raise PreventUpdate

无论如何,这是具有我描述的逻辑的代码:

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

from dash.exceptions import PreventUpdate

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}

dataset = pd.read_csv('values.csv')


def generate_graph(df):

    labels = list(set(df.source.values)) + list(set(df.target.values))

    fig = go.Figure(data=[
        go.Sankey(node=dict(pad=15, thickness=20, line=dict(color="black", width=0.5), label=labels, color="blue"),
                  link=dict(source=df.source.apply(lambda x: labels.index(x)),
                            target=df.target.apply(lambda x: labels.index(x)),
                            value=df.value))
    ])

    return fig


app.layout = html.Div([
    dcc.Dropdown(
        id='dataCenter_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['Data Center'].unique()] + [
            {'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Data Center'),
    dcc.Dropdown(
        id='customer_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['Customer'].unique()] + [
            {'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select Customer'),

    dcc.Dropdown(
        id='companyID_dropdown',
        options=[{'label': i, 'value': i} for i in dataset['companyID'].unique()] + [
            {'label': 'Select all', 'value': 'allID'}],
        multi=True, placeholder='Please select companyID'),

    dcc.Graph(id='uxrPerfGoalSankey', figure=generate_graph(dataset))
])


@app.callback(
    Output('uxrPerfGoalSankey', 'figure'),
    [Input('dataCenter_dropdown', 'value'),
     Input('customer_dropdown', 'value'),
     Input('companyID_dropdown', 'value')])
def update_graph(dataCenter, customer, companyID):

    if dataCenter is None or len(dataCenter) == 0 or 'allID' in dataCenter:
        dataCenter = dataset['Data Center']
    elif not isinstance(dataCenter, list):
        dataCenter = [dataCenter]

    if customer is None or len(customer) == 0 or 'allID' in customer:
        customer = dataset['Customer']
    elif not isinstance(customer, list):
        customer = [customer]

    if companyID is None or len(companyID) == 0 or 'allID' in companyID:
        companyID = dataset['companyID']
    elif not isinstance(companyID, list):
        companyID = [companyID]

    df = dataset[
        (dataset['Data Center'].isin(dataCenter)) &
        (dataset['Customer'].isin(customer)) &
        (dataset['companyID'].isin(companyID))
        ]

    return generate_graph(df)


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

对我来说运行良好,如果出现任何其他问题请告诉我。