【问题标题】:IndexError: list index out of range in chained callbackIndexError:链式回调中的列表索引超出范围
【发布时间】:2022-11-15 14:29:16
【问题描述】:

第二个下拉列表如何根据第一个下拉列表自动显示值? 根据第一个下拉列表中的选择,第二个下拉列表只有一个值可用。

样本数据:

data = {'Product ID': {0: 'P1', 1: 'P2', 2: 'P3', 3: 'P4', 4: 'P5', 5: 'P1', 6: 'P2', 7: 'P3', 8: 'P4', 9: 'P5'}, 'Sale ID': {0: 'Sale 001', 1: 'Sale 002', 2: 'Sale 003', 3: 'Sale 004', 4: 'Sale 005', 5: 'Sale 006', 6: 'Sale 007', 7: 'Sale 008', 8: 'Sale 009', 9: 'Sale 010'},  'Tnx Amount': {0: 100.0, 1: 101.0, 2: 102.0, 3: 103.0, 4: 104.0, 5: 100.0, 6: 101.0, 7: 102.0, 8: 103.0, 9: 104.0}, 'Tnx Date': {0: '01/10/2022', 1: '02/10/2022', 2: '03/10/2022', 3: '04/10/2022', 4: '05/10/2022', 5: '06/10/2022', 6: '07/10/2022', 7: '08/10/2022', 8: '09/10/2022', 9: '10/10/2022'}, 'Customer ID': {0: 'Cus01', 1: 'Cus02', 2: 'Cus03', 3: 'Cus04', 4: 'Cus05', 5: 'Cus01', 6: 'Cus02', 7: 'Cus03', 8: 'Cus04', 9: 'Cus05'}}

代码:


app.layout

app.layout = dbc.Container([
    dbc.Row([
        dbc.Col(html.H1("Tes",
                        className = 'text-center text-primary, mb-4 '
                        ,style={"textDecoration":"underline",'font-weight': 'bold'}),
                width=12
                ),
      
        ]),
    html.Br(),
    
    dbc.Row([
       dbc.Col([
           html.H3('Product'
                    ,style={'font-size': '25px'}
                   ),
           
           ], width=3, md=4),
       
       dbc.Col([            
           dcc.Dropdown(id='product_dd', value= None, #df['year'].max(),
                          options = [{'label':x, 'value':x} 
                                    for x in product_cat],
                          
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable= True
                          ),
           
           ], width=3, md=4),    
       
       
       ]),
    html.Br(),
    
    
    
    dbc.Row([       
        dbc.Col([            
            html.H3('Date'
                    ,style={'font-size': '25px'}
                    ),
            
            ], width=3, md=4),
    
        dbc.Col([            
            dcc.Dropdown(id='date_dd', value= '',                         
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable=True
                          
                          ),
            html.Br(),
            
            ], width=3, md=4),
        ], ), #style={"flexWrap": "wrap", "width":"250px"}
    html.Br(),
            
    dbc.Row([
          dbc.Col([
            html.H3('Sale ID'
                    ,style={'font-size': '25px'}
                    ),

              ], width=3, md=4),
          
          dbc.Col([          
              dcc.Dropdown(id='saleid_dd', value='',
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable=True
                          ),
                  
              html.Br(),
              
              ], width=3, md=4),
          

          ]),
    
    html.Br(), 
               
    dbc.Row([
       dbc.Col([
           html.H3('Customer ID'
                    ,style={'font-size': '25px'}
                   ),
           
           ], width=3, md=4),
       
       dbc.Col([            
           dcc.Dropdown(id='customer_dd', value= '',                         
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable= True
                          ),
           html.Br(),
           
           ], width=3, md=4),    
       
       
       ]),
    html.Br(),
            
])

@callback


@app.callback(
    Output('date_dd','options'),
    Input('product_dd', 'value')
    )


def update_dd (product_dd):
  
    date = df.drop_duplicates(['Date'], inplace= False)
    
    relevant_date = date[ df['Product'] == product_dd]['Date'].values.tolist()

    date_option= [dict(label=x,value=x)for x in relevant_date]
    
    
    return date_option


#first dropdown
@app.callback(
    Output('saleid_dd','options'),
    Input('date_dd', 'value')
    )


def update_dd (date_dd):
       
    saleid= df.drop_duplicates(['Sale ID'], inplace= False)
    
    relevant_id= saleid[ df['Date'] == date_dd]['Sale ID'].values.tolist()
    saleid_option= [dict(label=x,value=x)for x in relevant_id]
    
    
    return saleid_option



#second dropdown
@app.callback(
    Output('customer_dd','options'),
    Input('saleid_dd', 'value')
    )


def update_dd (saleid_dd):
  
    customer = df.drop_duplicates(['Customer ID'], inplace= False)
    
    relevant_customer = customer[ df['Sale ID'] == saleid_dd]['Customer ID'].values.tolist()

    cust_option= [dict(label=x,value=x)for x in relevant_customer]
    
    
    return cust_option
    

@app.callback(
    Output('customer_dd','value'),
    Input('customer_dd', 'options')
    )


def default_value(merchant):    
    return merchant[0]['value']

【问题讨论】:

  • 请提供minimal reproducible example 作为文本,而不是图像。另外,请检查您的格式。
  • 请写df.head(10).to_dict() 并将结果复制并粘贴到您的问题而不是图像。
  • 谢谢,现在通过添加 app.layout 添加完整示例,因为您只添加了回调
  • 谢谢,现在清楚了。您想根据第一个下拉菜单的选择来填充第二个下拉菜单,对吗?
  • 是的,第二个下拉菜单能够根据第一个下拉菜单自动显示值。

标签: python plotly-dash


【解决方案1】:

基于以上讨论。您可以使用相应列中的唯一值填充每个下拉菜单。我在下面的示例中只添加了app.layout

例子:

app.layout = dbc.Container([
    dbc.Row([
        dbc.Col(html.H1("Tes",
                        className = 'text-center text-primary, mb-4 '
                        ,style={"textDecoration":"underline",'font-weight': 'bold'}),
                width=12
                ),
      
        ]),
    html.Br(),
    
    dbc.Row([
       dbc.Col([
           html.H3('Product'
                    ,style={'font-size': '25px'}
                   ),
           
           ], width=3, md=4),
       
       dbc.Col([            
           dcc.Dropdown(id='product_dd', value= None, #df['year'].max(),
                          options = [{'label':x, 'value':x} 
                                    for x in product_cat["Product ID"].unique()],
                          
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable= True
                          ),
           
           ], width=3, md=4),    
       
       
       ]),
    html.Br(),
    
    
    
    dbc.Row([       
        dbc.Col([            
            html.H3('Date'
                    ,style={'font-size': '25px'}
                    ),
            
            ], width=3, md=4),
    
        dbc.Col([            
            dcc.Dropdown(id='date_dd', value= '',
                          options = [{'label':x, 'value':x} 
                                    for x in product_cat["Tnx Date"].unique()],
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable=True
                          
                          ),
            html.Br(),
            
            ], width=3, md=4),
        ], ), #style={"flexWrap": "wrap", "width":"250px"}
    html.Br(),
            
    dbc.Row([
          dbc.Col([
            html.H3('Sale ID'
                    ,style={'font-size': '25px'}
                    ),

              ], width=3, md=4),
          
          dbc.Col([          
              dcc.Dropdown(id='saleid_dd', value='',
                          options = [{'label':x, 'value':x} 
                                     for x in product_cat["Sale ID"].unique()],
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable=True
                          ),
                  
              html.Br(),
              
              ], width=3, md=4),
          

          ]),
    
    html.Br(), 
               
    dbc.Row([
       dbc.Col([
           html.H3('Customer ID'
                    ,style={'font-size': '25px'}
                   ),
           
           ], width=3, md=4),
       
       dbc.Col([            
           dcc.Dropdown(id='customer_dd', value= '', 
                        options = [{'label':x, 'value':x} 
                                     for x in product_cat["Customer ID"].unique()],
                          searchable = True, search_value='',
                          placeholder= 'Please select ...',
                          clearable= True
                          ),
           html.Br(),
           
           ], width=3, md=4),    
       
       
       ]),
    html.Br(),
            
])

输出:

【讨论】:

    【解决方案2】:

    我认为首先您需要先在布局中添加选项,然后使用回调返回新选项。请参考以下代码:

    import pandas as pd
    import numpy as np
    import plotly.express as px
    import dash
    import dash_html_components as html
    import dash_core_components as dcc
    from dash.dependencies import Input, Output
    import dash_bootstrap_components as dbc
    import plotly.graph_objects as go
    
    data = {'Product ID': {0: 'P1', 1: 'P2', 2: 'P3', 3: 'P4', 4: 'P5', 5: 'P1', 6: 'P2', 7: 'P3', 8: 'P4', 9: 'P5'}, 'Sale ID': {0: 'Sale 001', 1: 'Sale 002', 2: 'Sale 003', 3: 'Sale 004', 4: 'Sale 005', 5: 'Sale 006', 6: 'Sale 007', 7: 'Sale 008', 8: 'Sale 009', 9: 'Sale 010'},  'Tnx Amount': {0: 100.0, 1: 101.0, 2: 102.0, 3: 103.0, 4: 104.0, 5: 100.0, 6: 101.0, 7: 102.0, 8: 103.0, 9: 104.0}, 'Tnx Date': {0: '01/10/2022', 1: '02/10/2022', 2: '03/10/2022', 3: '04/10/2022', 4: '05/10/2022', 5: '06/10/2022', 6: '07/10/2022', 7: '08/10/2022', 8: '09/10/2022', 9: '10/10/2022'}, 'Customer ID': {0: 'Cus01', 1: 'Cus02', 2: 'Cus03', 3: 'Cus04', 4: 'Cus05', 5: 'Cus01', 6: 'Cus02', 7: 'Cus03', 8: 'Cus04', 9: 'Cus05'}}
    
    df = pd.DataFrame(data)
    
    app = dash.Dash(__name__,external_stylesheets=[dbc.themes.LUX])
    app.layout = dbc.Container([
        dbc.Row([
            dbc.Col(html.H1("Tes",
                            className = 'text-center text-primary, mb-4 '
                            ,style={"textDecoration":"underline",'font-weight': 'bold'}),
                    width=12
                    ),
          
            ]),
        html.Br(),
        
        dbc.Row([
           dbc.Col([
               html.H3('Product'
                        ,style={'font-size': '25px'}
                       ),
               
               ], width=3, md=4),
           
           dbc.Col([            
               dcc.Dropdown(id='product_dd',
                            options = [{'label':x, 'value':x} 
                                        for x in df['Product ID'].unique()],
                            value=[],
                            searchable = True,
                            placeholder= 'Please select ...',
                            multi=True,
                            clearable= True)
               ], width=3, md=4),    
           ]),
        html.Br(),
        dbc.Row([       
            dbc.Col([            
                html.H3('Date'
                        ,style={'font-size': '25px'}
                        )], width=3, md=4),
            dbc.Col([            
                dcc.Dropdown(id='date_dd', 
                             options = [{'label':x, 'value':x} 
                                        for x in df['Tnx Date'].unique()],
                             value=[],
                             searchable = True,
                             placeholder= 'Please select ...',
                             clearable=True,
                            multi=True,),
                html.Br(),
            ], width=3, md=4),
        ]), #style={"flexWrap": "wrap", "width":"250px"}
        html.Br(),
     
        dbc.Row([
              dbc.Col([
                html.H3('Sale ID'
                        ,style={'font-size': '25px'})
              ], width=3, md=4),
              
              dbc.Col([          
                  dcc.Dropdown(id='saleid_dd',
                               options = [{'label':x, 'value':x} 
                                        for x in df['Sale ID'].unique()],
                               value=[],
                               searchable = True,
                               placeholder= 'Please select ...',
                               clearable=True,
                            multi=True,
                              ),
                  html.Br(),
              
              ], width=3, md=4),
        ]),
        html.Br(), 
                   
        dbc.Row([
           dbc.Col([
               html.H3('Customer ID'
                        ,style={'font-size': '25px'}
                      )
           ], width=3, md=4),
           
           dbc.Col([            
               dcc.Dropdown(id='customer_dd',
                            options = [{'label':x, 'value':x} 
                                        for x in df['Customer ID'].unique()], 
                            value=[],
                            searchable = True,
                            placeholder= 'Please select ...',
                            clearable= True,
                            multi=True,
                           ),
               html.Br(),
           ], width=3, md=4),
        ]),
        html.Br(),
    ])
    
    
    @app.callback(
        Output('product_dd','options'),
        [Input('date_dd', 'value'), 
        Input('saleid_dd','value'),
        Input('customer_dd','value')]
        )
    
    def update_dd (date_dd,saleid_dd,customer_dd):
        if date_dd != [] and saleid_dd != [] and customer_dd != []:
            df1 = df[df['Tnx Date'].isin(date_dd)]
            df2 = df1[df1['Sale ID'].isin(saleid_dd)]
            dff = df2[df2['Customer ID'].isin(customer_dd)]       
        elif date_dd != [] and saleid_dd == [] and customer_dd != []:
            df1 = df[df['Tnx Date'].isin(date_dd)]
            dff = df1[df1['Customer ID'].isin(customer_dd)]          
        elif date_dd != [] and saleid_dd != [] and customer_dd == []:
            df1 = df[df['Tnx Date'].isin(date_dd)]
            dff = df1[df1['Sale ID'].isin(saleid_dd)]      
        elif date_dd != [] and saleid_dd == [] and customer_dd == []:
            dff = df[df['Tnx Date'].isin(date_dd)]
        elif date_dd == [] and saleid_dd != [] and customer_dd != []:
            df1 = df[df['Sale ID'].isin(saleid_dd)]       
            dff = df1[df1['Customer ID'].isin(customer_dd)]
        elif date_dd == [] and saleid_dd != [] and customer_dd == []:
            dff = df[df['Sale ID'].isin(saleid_dd)]       
        elif date_dd == [] and saleid_dd == [] and customer_dd != []:
            dff = df[df['Customer ID'].isin(customer_dd)] 
        elif date_dd == [] and saleid_dd == [] and customer_dd == []:
            dff = df.copy()
        return [{'label':x,'value':x} for x in dff['Product ID'].unique()]
    
    
    
    @app.callback(
        Output('date_dd','options'),
        [Input('product_dd', 'value'),
        Input('saleid_dd','value'),
        Input('customer_dd','value')]
        )
    
    def update_dd (product_dd,saleid_dd,customer_dd):
        if product_dd != [] and saleid_dd != [] and customer_dd != []:
            df1 = df[df['Product ID'].isin(product_dd)]
            df2 = df1[df1['Sale ID'].isin(saleid_dd)]
            dff = df2[df2['Customer ID'].isin(customer_dd)]       
        elif product_dd != [] and saleid_dd == [] and customer_dd != []:
            df1 = df[df['Product ID'].isin(product_dd)]
            dff = df1[df1['Customer ID'].isin(customer_dd)]          
        elif product_dd != [] and saleid_dd != [] and customer_dd == []:
            df1 = df[df['Product ID'].isin(product_dd)]
            dff = df1[df1['Sale ID'].isin(saleid_dd)]      
        elif product_dd != [] and saleid_dd == [] and customer_dd == []:
            dff = df[df['Product ID'].isin(product_dd)]
        elif product_dd == [] and saleid_dd != [] and customer_dd != []:
            df1 = df[df['Sale ID'].isin(saleid_dd)]       
            dff = df1[df1['Customer ID'].isin(customer_dd)]
        elif product_dd == [] and saleid_dd != [] and customer_dd == []:
            dff = df[df['Sale ID'].isin(saleid_dd)]       
        elif product_dd == [] and saleid_dd == [] and customer_dd != []:
            dff = df[df['Customer ID'].isin(customer_dd)] 
        elif product_dd == [] and saleid_dd == [] and customer_dd == []:
            dff = df.copy()
        return [{'label':x,'value':x} for x in dff['Tnx Date'].unique()]
    
    @app.callback(
        Output('saleid_dd','options'),
        [Input('product_dd', 'value'), 
        Input('date_dd','value'), 
        Input('customer_dd','value')]
        )
    
    def update_dd (product_dd,date_dd,customer_dd):
        if product_dd != [] and date_dd != [] and customer_dd != []:
            df1 = df[df['Product ID'].isin(product_dd)]        
            df2 = df1[df1['Tnx Date'].isin(date_dd)]
            dff = df2[df2['Customer ID'].isin(customer_dd)]       
        elif product_dd != [] and date_dd == [] and customer_dd != []:
            df1 = df[df['Product ID'].isin(product_dd)] 
            dff = df1[df1['Customer ID'].isin(customer_dd)]          
        elif product_dd != [] and date_dd != [] and customer_dd == []:
            df1 = df[df['Product ID'].isin(product_dd)] 
            dff = df1[df1['Tnx Date'].isin(date_dd)]      
        elif product_dd != [] and date_dd == [] and customer_dd == []:
            dff = df[df['Product ID'].isin(product_dd)] 
        elif product_dd == [] and date_dd != [] and customer_dd != []:
            df1 = df[df['Tnx Date'].isin(date_dd)]       
            dff = df1[df1['Customer ID'].isin(customer_dd)]
        elif product_dd == [] and date_dd != [] and customer_dd == []:
            dff = df[df['Tnx Date'].isin(date_dd)]        
        elif product_dd == [] and date_dd == [] and customer_dd != []:
            dff = df[df['Customer ID'].isin(customer_dd)] 
        elif product_dd == [] and date_dd == [] and customer_dd == []:
            dff = df.copy()
        return [{'label':x,'value':x} for x in dff['Sale ID'].unique()]
    
    @app.callback(
        Output('customer_dd','options'), 
        [Input('product_dd', 'value'), 
        Input('date_dd','value'), 
        Input('saleid_dd','value')]
        )
    
    def update_dd (product_dd,date_dd,saleid_dd):
        if product_dd != [] and date_dd != [] and saleid_dd != []:
            df1 = df[df['Product ID'].isin(product_dd)]        
            df2 = df1[df1['Tnx Date'].isin(date_dd)]
            dff = df2[df2['Sale ID'].isin(saleid_dd)]       
        elif product_dd != [] and date_dd == [] and saleid_dd != []:
            df1 = df[df['Product ID'].isin(product_dd)] 
            dff = df1[df1['Sale ID'].isin(saleid_dd)]          
        elif product_dd != [] and date_dd != [] and saleid_dd == []:
            df1 = df[df['Product ID'].isin(product_dd)] 
            dff = df1[df1['Tnx Date'].isin(date_dd)]      
        elif product_dd != [] and date_dd == [] and saleid_dd == []:
            dff = df[df['Product ID'].isin(product_dd)] 
        elif product_dd == [] and date_dd != [] and saleid_dd != []:
            df1 = df[df['Tnx Date'].isin(date_dd)]       
            dff = df1[df1['Sale ID'].isin(saleid_dd)]
        elif product_dd == [] and date_dd != [] and saleid_dd == []:
            dff = df[df['Tnx Date'].isin(date_dd)]        
        elif product_dd == [] and date_dd == [] and saleid_dd != []:
            dff = df[df['Sale ID'].isin(saleid_dd)] 
        elif product_dd == [] and date_dd == [] and saleid_dd == []:
            dff = df.copy()
        return [{'label':x,'value':x} for x in dff['Customer ID'].unique()]
    
    
    if __name__ == "__main__":
        app.run_server(debug=False,port=1217)
    

    【讨论】:

    • 嗨,每个下拉菜单也可以单独工作吗?
    • @beginofwork:我想你可以查看我之前的答案,它也可以单独工作。
    • 以及如何让下拉菜单自动显示值?
    • 正如我所说,首先您应该先添加下拉选项,然后使用回调为它们返回新选项。如果您希望它是独立的并且也可以单独工作,您应该在回调中添加详细条件。 stackoverflow.com/questions/74173240/…
    • dcc.Dropdown 中添加了选项,但仍然无法单独工作
    猜你喜欢
    • 1970-01-01
    • 2011-10-31
    • 2015-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多