Black Lives Matter. Please consider donating to Black Girls Code today.

Multiple Dropdowns and RangeSliders that depend on eachother

Hi, I have first dropdown ‘country’ that can accept multiple selections. Below that are two range sliders Year and Mont that depend on and change according to which countries has been selected in the country dropdown. Below range sliders are other multiple dropdowns which also accept multiple selections and they all depend on the which values were selected in dropdowns and range sliders above and show only related values to the selections. I also have one dropdown that has independent columns that need to be plotted against all selected values above. I need multiple plots for different that have been selected for this last dropdown. I am taking values form Pandas dataframe and filtering it. This is what I have so far but it doesn’t work with multiple selections and not sure how to make multiple plots. I need to have multiple plots for all different values selected. Also, RanggeSliders are giving me ‘index out of bounds error’ and dropdowns are either not being populated with correct values or not populated at all. Any help is appreciated.

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import matplotlib.pyplot as plt
import plotly.graph_objs as go
import numpy as np
import plotly.plotly as py

app = dash.Dash(__name__)

df = pd.read_csv('some_file.csv')

columns = df.columns

app.layout = html.Div([
            
            html.Div([
                dcc.Dropdown(
                    id='dropdown-country', 
                    multi=True,
                    options=[{'label': i, 'value': i} for i in df.country.unique()],
                    placeholder="Country",
                    value='Country:')], 
                style={'width': '30%', 'margin-top': 60}), 
            html.Div([
                html.H4("Choose Year Range:"),
                dcc.RangeSlider(
                    id='dropdown-year',
                    #marks={i: '{}'.format(i) for i in range(max(df.Year.unique()))},
                    min=1991,
                    max=2045,
                    updatemode='mouseup',
                ), 
                        
                html.Div(id='updateyear-output-container', style={'margin-top': 20}),
                html.H4("Choose Month Range:"),
                dcc.RangeSlider(
                    id='dropdown-month',
                    min=0,
                    max=12,
                    updatemode='mouseup'
                ),
            html.Div(id='updatemonth-output-container', style={'margin-top': 20})], 
            style={'width': '25%', 'margin-left': '50px', 'margin-top': 40}),
            
            html.Div([
                dcc.Dropdown(
                    id='dropdown-car-names',
                    multi=True,
                    options=[{'label': i, 'value': i} for i in df.car_name.unique()],
                    placeholder="Car Name",
                    value='Car',
                )],
                style={'width': '30%', 'margin-top': 20}),
            html.Div([
                dcc.Dropdown(
                    id='dropdown-type',
                    multi=True,
                    options=[{'label': i, 'value': i} for i in df.Type.unique()],
                    placeholder="Type",
                    value='Type'
                )],
                style={'width': '30%', 'margin-top': 20}),
            html.Div([
                dcc.Dropdown(
                    id='dropdown-subtype',
                    multi=True,
                    options=[{'label': i, 'value': i} for i in df.SubType.unique()],
                    placeholder="SubType",
                    value='SubType'
                )],
                style={'width': '30%', 'margin-top': 20}),
            html.Div([
                dcc.Dropdown(
                    id='dropdown-color',
                    multi=True,
                    options=[{'label': i, 'value': i} for i in df.color.unique()],
                    placeholder="color",
                    value='Color'
                )],
                style={'width': '30%', 'margin-top': 20}),
            html.Div([
                dcc.Dropdown(
                    id='dropdown-manufacturer',
                    multi=True,
                    options=[{'label': i, 'value': i} for i in df.manufacturer.unique()],
                    placeholder="Manufacturer",
                    value='Manufacturer'
                )],
            style={'width': '30%', 'margin-top': 20}),
            html.Div([
                dcc.Dropdown(
                    id='dropdown-to-plot', 
                    multi=True,
                    options=['float-vals-1', 'float-vals-2', 'float-vals-3', ..., 'float-vals-15'],
                    placeholder="Select column you wish to plot",
                )],
                style={'width': '30%', 'margin-top': 20}),
            html.Div(dcc.Graph(id='indicator-graphic'),
                     style={'margin-top': '-650px', 'margin-left': '600px'})
            #html.Div([html.Img(id ='cur_plot', src ='')], id='plot_div', 
                      #style={'margin-top': '-650px', 'margin-left': '600px'}),
    ])

@app.callback(
    dash.dependencies.Output('updateyear-output-container', 'children'),
    [dash.dependencies.Input('dropdown-year', 'value')])
def print_year_slider_value(selected_year):
      return 'Selected year range: {}-{}'.format(selected_year[0], selected_year[1])

@app.callback(
    dash.dependencies.Output('updatemonth-output-container', 'children'),
    [dash.dependencies.Input('dropdown-month', 'value')])
def print_month_slider_value(selected_month):
    return 'Selected month range: {}-{}'.format(selected_month[0], selected_month[1])

@app.callback(
    dash.dependencies.Output('dropdown-year', 'value'),
    [dash.dependencies.Input('dropdown-country', 'value')])
def set_year_slider_options(selected_country):
    years = df[df.country.isin([selected_country])].Year.values
    return [years[0], years[1]]

@app.callback(
     dash.dependencies.Output('dropdown-month', 'value'),
     [dash.dependencies.Input('dropdown-country', 'value'),
      dash.dependencies.Input('dropdown-year', 'value')])
def set_month_slider_options(selected_country, selected_year):
    months = df[(df.country.isin([selected_country])) &  
                 (df.Year >= selected_year[0]) & 
                 (df.Year <= selected_year[1])].Month.values
    return [months[0], months[1]]

@app.callback(
    dash.dependencies.Output('dropdown-car-names', 'options'),
    [dash.dependencies.Input('dropdown-country', 'value'),
     dash.dependencies.Input('dropdown-year', 'value'),
     dash.dependencies.Input('dropdown-month', 'value')])
def set_car_names_options(selected_country, 
                             selected_year,
                             selected_month):
    car_names = df[(df.country.isin([selected_country])) & 
                    (df.Year >= selected_year[0]) & 
                    (df.Year <= selected_year[1]) &
                    (df.Month >= selected_month[0]) &
                    (df.Month <= selected_month[1])].car_names.values
    return [{'label': i, 'value': i} for i in car_names]

@app.callback(
    dash.dependencies.Output('dropdown-car-names', 'value'),
    [dash.dependencies.Input('dropdown-car-names', 'options')])
def set_car_names_value(available_options):
    return available_options[0]['value']

@app.callback(
    dash.dependencies.Output('dropdown-type', 'options'),
    [dash.dependencies.Input('dropdown-country', 'value'),
     dash.dependencies.Input('dropdown-year', 'value'),
     dash.dependencies.Input('dropdown-month', 'value'),
     dash.dependencies.Input('dropdown-car-names', 'value')])
def set_type_options(selected_country, selected_year, 
                     selected_month, selected_car_names):
    types = df[df.country.isin([selected_country]) & 
               (df.Year >= selected_year[0]) & 
               (df.Year <= selected_year[1]) &
               (df.Month >= selected_month[0]) &
               (df.Month <= selected_month[1]) & 
               (df.Type.isin([selected_car_names]))].Type.values
    return [{'label': i, 'value': i} for i in types]

@app.callback(
    dash.dependencies.Output('dropdown-type', 'value'),
    [dash.dependencies.Input('dropdown-type', 'options')])
def set_type_value(available_options):
    return available_options[0]['value'] 

@app.callback(
    dash.dependencies.Output('dropdown-subtype', 'options'),
    [dash.dependencies.Input('dropdown-country', 'value'),
     dash.dependencies.Input('dropdown-year', 'value'),
     dash.dependencies.Input('dropdown-month', 'value'),
     dash.dependencies.Input('dropdown-car-names', 'value'),
     dash.dependencies.Input('dropdown-type', 'value')])
def set_subtype_options(selected_country, selected_year,
                        selected_month, selected_car_names, 
                        selected_type):
    sub_types = df[(df.country.isin([selected_country])) & 
               (df.Year >= selected_year[0]) & 
               (df.Year <= selected_year[1]) &
               (df.Month >= selected_month[0]) &
               (df.Month <= selected_month[1]) & 
               (df.car_name.isin([selected_car_names])) &
               (df.Type.isin([selected_type]))].SubType.values
    return [{'label': i, 'value': i} for i in sub_types]

@app.callback(
    dash.dependencies.Output('dropdown-subtype', 'value'),
    [dash.dependencies.Input('dropdown-subtype', 'options')])
def set_subtype_value(available_options):
    return available_options[0]['value']

@app.callback(
    dash.dependencies.Output('dropdown-color', 'options'),
    [dash.dependencies.Input('dropdown-country', 'value'),
     dash.dependencies.Input('dropdown-year', 'value'),
     dash.dependencies.Input('dropdown-month', 'value'),
     dash.dependencies.Input('dropdown-car-types', 'value'),
     dash.dependencies.Input('dropdown-type', 'value'),
     dash.dependencies.Input('dropdown-subtype', 'value')])
def set_color_options(selected_country, selected_year, 
                        selected_month, selected_car_types, 
                        selected_type, selected_subtype):
    colors = df[(df.country.isin([selected_country])) & 
               (df.Year >= selected_year[0]) & 
               (df.Year <= selected_year[1]) &
               (df.Month >= selected_month[0]) &
               (df.Month <= selected_month[1]) & 
               (df.car_name.isin([selected_car_types])) &
               (df.Type.isin([selected_type])) &
               (df.SubType.isin([selected_subtype]))].color.values
    return [{'label': i, 'value': i} for i in colors]

@app.callback(
    dash.dependencies.Output('dropdown-manufacturer', 'value'),
    [dash.dependencies.Input('dropdown-manufacturer', 'options')])
def set_color_value(available_options):
    return available_options[0]['value']

@app.callback(
    dash.dependencies.Output('dropdown-manufacturer', 'options'),
    [dash.dependencies.Input('dropdown-country', 'value'),
     dash.dependencies.Input('dropdown-year', 'value'),
     dash.dependencies.Input('dropdown-month', 'value'),
     dash.dependencies.Input('dropdown-car-names', 'value'),
     dash.dependencies.Input('dropdown-type', 'value'),
     dash.dependencies.Input('dropdown-subtype', 'value'),
     dash.dependencies.Input('dropdown-color', 'value')])
def set_manufacturer_options(selected_country, selected_year,
                        selected_month, selected_car_names, 
                        selected_type, selected_subtype,
                        selected_color):
    man = df[(df.country.isin([selected_country])) &  
               (df.Year >= selected_year[0]) & 
               (df.Year <= selected_year[1]) &
               (df.Month >= selected_month[0]) &
               (df.Month <= selected_month[1]) & 
               (df.car_name[df.car_name.isin([selected_car_names])]) &
               (df.Type.isin([selected_type])) &
               (df.SubType.isin([selected_subtype])) & 
               (df.color.isin([selected_color]))].manufacturer.values

    return [{'label': i, 'value': i} for i in man]

@app.callback(
    dash.dependencies.Output('dropdown-manufacturer', 'value'),
    [dash.dependencies.Input('dropdown-manufacturer', 'options')])
def set_manufacturer_value(available_options):
    return available_options[0]['value']

def set_plotting_options():
    plots = ['float-vals-1', 'float-vals-2', 'float-vals-3', ..., 'float-vals-15']
    return [{'label': i, 'value': i} for i in plots]

@app.callback(
    dash.dependencies.Output('dropdown-to-plot', 'value'),
    [dash.dependencies.Input('dropdown-to-plot', 'options')])
def set_plotting_value(available_options):
    return available_options[0]['value']

@app.callback(
    dash.dependencies.Output('indicator-graphic', 'figure'),
    [dash.dependencies.Input('dropdown-country', 'value'),
     dash.dependencies.Input('dropdown-year', 'value'),
     dash.dependencies.Input('dropdown-month', 'value'),
     dash.dependencies.Input('dropdown-car-names', 'value'),
     dash.dependencies.Input('dropdown-type', 'value'),
     dash.dependencies.Input('dropdown-subtype', 'value'),
     dash.dependencies.Input('dropdown-car-names', 'value'),
     dash.dependencies.Input('dropdown-color', 'value'),
     dash.dependencies.Input('dropdown-manufacturer', 'value')])
def update_graph(selected_country, selected_year,
                 selected_month, selected_car_names, 
                selected_type, selected_subtype,
                selected_color, selected_manufacturer, selected_plot):
    
    
    dff = df.loc[(df.country.isin(selected_country)) &
              (df.Year >= selected_year[0]) & 
              (df.Year <= selected_year[1]) &
              (df.Month >= selected_month[0]) &
              (df.Month <= selected_month[1]) &
              (df.car_types.isin([selected_car_names])) &
              (df.Type.isin([selected_type])) & 
              (df.SubType.isin([selected_subtype])) & 
              (df.color.isin([selected_color])) &
              (df.manufacturer.isin([selected_manufacturer])), selected_plot]
    
    #this is wrong, needs to be changed but not sure how. It has to show multiple plots for every country selected, for every plotting options selected and everything else selected.
    traces = []
    for country in selected_country:
        df_ = dff[dff['country'] == country]
        traces.append(go.Scatter(
            x=df_['Year'],
            y=df_[selected_plot],
            text=df_['country'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            },
            name=country
        ))