2

I have nested data that are name of the area / district, so each area have several sub area, and each sub area have several sub-sub area.

And I edit my question base on progress that i have, well I start learn dash since last Saturday.

This is my fourth edit question, and the question change to blog... how to do it, because i answer it by my self everything...

I put here the answer, hope useful for somebody there.

I will explain few days ago, I have problem, to create interactive dashboard. especially to create menus to make it, responsive.

My data have structure like this:

So, the data is about 2 city that is city a and city z.

City a have 2 district, that is, district b and district c. City z have 2 district, that is, district x and district y.

District b has 2 area: area d and area e District c has 2 area: area f and area g

It is better that I show you. How to handle problem like this.

    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    from plotly import graph_objs as go
    import dash_bootstrap_components as dbc
    import plotly.express as px
    from dash.dependencies import Input, Output, State
    import pandas as pd

    # this is the data of the city
    data = [['a','b','d','h'],
           ['a','b','d','i'],
           ['a','b','e','j'],
           ['a','b','e','k'],
           ['a','c','f','l'],
           ['a','c','f','m'],
           ['a','c','g','n'],
           ['a','c','g','o'],
           ['z','x','p','a1'],
           ['z','x','p','a2'],
           ['z','x','q','a3'],
           ['z','x','q','a4'],
           ['z','y','r','a5'],
           ['z','y','r','a6'],
           ['z','y','s','a7'],
           ['z','y','s','a8']]

    df = pd.DataFrame(data)
    df.columns = ['city', 'district', 'area', 'subarea']


    # now I want to create 4 dropdown menu that represented the area level.
    # I want to make every time I change the higher level of area, 
    # the options in the lower dropdown menu that representative lower area change.
    
    city_list = list(set(df['city'].to_list()))
    city_list.insert(0,'all city')

   

    # subarea
    # ===============
    def search_area_from_subarea(area_name):
        area_level = list(set(df[df.loc[:, 'subarea'] == area_name]['area'].to_list()))[0]
        return area_level
    
    def search_district_from_subarea(area_name):
        area_level = list(set(df[df.loc[:, 'subarea'] == area_name]['district'].to_list()))[0]
        return area_level
    
    def search_city_from_subarea(area_name):
        area_level = list(set(df[df.loc[:, 'subarea'] == area_name]['city'].to_list()))[0]
        return area_level
    
    # area
    # ===============
    def search_district_from_area(area_name):
        area_level = list(set(df[df.loc[:, 'area'] == area_name]['district'].to_list()))[0]
        return area_level
    
    def search_city_from_area(area_name):
        area_level = list(set(df[df.loc[:, 'area'] == area_name]['city'].to_list()))[0]
        return area_level
    
    # district
    # ============
    def search_city_from_district(area_name):
        area_level = list(set(df[df.loc[:, 'district'] == area_name]['city'].to_list()))[0]
        return area_level

    app = dash.Dash()
    app.layout= html.Div([
       dbc.Nav(
           [
            dcc.Dropdown(
                 id='menu_city', clearable=False,
                 value='all city', options=[
                 {'label': c1, 'value': c1}
                 for c1 in city_list]),
    
              dcc.Dropdown(
                 id='menu_district', clearable=False,
                 value='all district'),
                dcc.Dropdown(
                 id='menu_area', clearable=False,
                 value='all area'),
                    dcc.Dropdown(
                 id='menu_subarea', clearable=False,
                 value='all subarea'),
               html.Hr(),
               dbc.Button(id='button_show',children="SHOW DATA", color="info", className="mr-1")
             ]), 
     html.Div([
        dbc.Row(
            dbc.Col([
                html.H2(id='title_for_test')],
                align='right', width={'size': '10', 'offset': '2'}
            )
              )
           ])
      ])
                    
    # CALLBACK SECTION

    # ========================================
    # CALLBACK CONFIGURATION FOR DROPDOWN LIST
    # ========================================
    # confifuration to set district dropdown menu change base selection on city dropdown menu

    @app.callback(dash.dependencies.Output('menu_district','options'),
                  [Input('menu_city', 'value')])
                  
    def set_list(selected_options):
        if selected_options == 'all city':
            temp_list = list(set(df['district'].to_list()))
            temp_list.insert(0, 'all district')
            return [{'label': i, 'value': i} for i in temp_list]
        else:
            temp_list = list(set(df[df.loc[:,'city'] == selected_options]['district'].to_list()))
            temp_list.insert(0, 'all district')
            return [{'label': i, 'value': i} for i in temp_list]
    # -----------------------------
    # configuration to prevent district dropdown menu error
    @app.callback(dash.dependencies.Output('menu_district','value'),
                  [Input('menu_district', 'options')])
                  
    def set_list(selected_options):
        return selected_options[0]['value']
    
    
    
    
    # =======================================
    # confifuration to set area dropdown menu change base selection on district dropdown menu
    
    @app.callback(dash.dependencies.Output('menu_area','options'),
                  [Input('menu_city', 'value')],
                  [Input('menu_district', 'value')],
                 multi = True)
                  
    def set_list(selected_options1, selected_options2):
        # 2 input, means: 2**2 possibility
        #print('1',selected_options1)
        #print('2', selected_options2)
        
        if selected_options1 == 'all city' and selected_options2 == 'all district':
            temp_list = list(set(df['area'].to_list()))
            temp_list.insert(0, 'all area')
            return [{'label': i, 'value': i} for i in temp_list]
        
        if selected_options1 != 'all city' and selected_options2 == 'all district':
            temp_list = list(set(df[(df.loc[:,'district'] == selected_options2)]['area'].to_list()))
            temp_list.insert(0, 'all area')
            return [{'label': i, 'value': i} for i in temp_list]
        
        if selected_options1 == 'all city' and selected_options2 != 'all district':
            temp_list = list(set(df[(df.loc[:,'district'] == selected_options2)]['area'].to_list()))
            temp_list.insert(0, 'all area')
            return [{'label': i, 'value': i} for i in temp_list]
        
        if selected_options1 != 'all city' and selected_options2 != 'all district':
            temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) & (df.loc[:,'district'] == selected_options2)]['area'].to_list()))
            temp_list.insert(0, 'all area')
            return [{'label': i, 'value': i} for i in temp_list]
        
    # -----------------------------
    # configuration to prevent area dropdown menu error
    
    @app.callback(dash.dependencies.Output('menu_area','value'),
                  [Input('menu_area', 'options')])
    
    
    
    
    # ========================================
    # confifuration to set subarea dropdown menu change base selection on area dropdown menu
    
    @app.callback(dash.dependencies.Output('menu_subarea','options'),
                  [Input('menu_city', 'value')],
                  [Input('menu_district', 'value')],
                  [Input('menu_area', 'value')],
                  multi=True
                 )
                  
    def set_list(selected_options1,selected_options2, selected_options3):
        # 3 input = 2**3 possibility
        
        # possibility 1:
        if selected_options1 == 'all city' and selected_options2 == 'all district' and selected_options3 == 'all area':
            temp_list = list(set(df['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        
        # possibility 2:
        if selected_options1 == 'all city' and selected_options2 == 'all district' and selected_options3 != 'all area':
            temp_list = list(set(df[(df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        # possibility 3:
        if selected_options1 == 'all city' and selected_options2 != 'all district' and selected_options3 == 'all area':
            temp_list = list(set(df[(df.loc[:,'district'] == selected_options2)]['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        # possibility 4:
        if selected_options1 != 'all city' and selected_options2 == 'all district' and selected_options3 == 'all area':
            temp_list = list(set(df[(df.loc[:,'city'] == selected_options1)]['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        
        
        # possibility 5:
        if selected_options1 != 'all city' and selected_options2 != 'all district' and selected_options3 == 'all area':
            temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) & (df.loc[:,'district'] == selected_options2)]['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        
        # possibility 6:
        if selected_options1 != 'all city' and selected_options2 == 'all district' and selected_options3 != 'all area':
            temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) & (df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        
        # possibility 7:
        if selected_options1 == 'all city' and selected_options2 != 'all district' and selected_options3 != 'all area':
            temp_list = list(set(df[(df.loc[:,'district'] == selected_options2) & (df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        
        # possibility 8:
        if selected_options1 != 'all city' and selected_options2 != 'all district' and selected_options3 != 'all area':
            temp_list = list(set(df[(df.loc[:,'city'] == selected_options1) & (df.loc[:,'district'] == selected_options2) & (df.loc[:,'area'] == selected_options3)]['subarea'].to_list()))
            temp_list.insert(0, 'all subarea')
            return [{'label': i, 'value': i} for i in temp_list]
        
        
    # -----------------------------
    # configuration to prevent subarea dropdown menu error
    @app.callback(dash.dependencies.Output('menu_subarea','value'),
                  [Input('menu_subarea', 'options')])
    
    def set_list(selected_options):
        return selected_options[0]['value']
    

    # ================================
    # CONFIGURATION SECTION FOR CALLBACK BUTTON 
    # ================================
    #configuration callback button
    @app.callback(dash.dependencies.Output('title_for_test','children'),
                  [Input('button_show', 'n_clicks' )],
                  [State('menu_city', 'value')],
                  [State('menu_district', 'value')],
                  [State('menu_area', 'value')],
                  [State('menu_subarea', 'value')],
                 multi=True)
    
    def executor(n_clicks, number1, number2, number3, number4):
        
        
        # provinsi
        if number1 == 'all city' and number2 == 'all district' and number3 == 'all area' and number4 == 'all subarea':
            return 'demografic data of my state'
        
        
        # city / city
        if number1 != 'all city' and number2 == 'all district' and number3 == 'all area' and number4 == 'all subarea':
            return 'demografic data of ' + number1 + ' city'
            
            
        # district    
        if (number1 == 'all city' or number1 != 'all city') and number2 != 'all district' and number3 == 'all area' and number4 == 'all subarea':
            return 'demografic data district ' + number2 + ', city ' + search_city_from_district(number2)
    
    
        # area
        if (number1 == 'all city' or number1 != 'all city') and (number2 == 'all district' or number2 != 'all district') and number3  != 'all area' and number4 == 'all subarea':
            return 'demografic data area ' + number3 ,html.Br(), 'district ' + search_district_from_area(number3) +  ', city ' + search_city_from_area(number3)
    
        # subarea
        if (number1 == 'all city' or number1 != 'all city') and (number2 != 'all district' or number2 == 'all district') and (number3  != 'all area' or number3  == 'all area') and number4 != 'all subarea':
            return 'demografic data subarea ' + number4 + ', area ' + search_area_from_subarea(number4),html.Br(),'district ' + search_district_from_subarea(number4) + ', city ' + search_city_from_subarea(number4)


    if __name__ == "__main__":
        app.run_server()

That is the problem finished.

Claire
  • 639
  • 9
  • 25
Wahyu Bram
  • 413
  • 1
  • 7
  • 13
  • 2
    Maybe you can consider structure your problem & solution as Q&A, and post your solution as answer below? – Claire Dec 16 '20 at 10:05

0 Answers0