Failed component prop type: Invalid component prop `options[0]` key `and_ones` supplied to Dropdown

I am trying to have multi-dropdown menus that displays value of last selected dropdown menu but I keep getting the error in the title.

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
from dash.exceptions import PreventUpdate
import pandas as pd


app = dash.Dash(__name__)

from sportsipy.nba.teams import Teams
teams = Teams()
team_abbrev = [team.abbreviation for team in teams]
team_selections=[{'label': k, 'value': k} for k in team_abbrev]
basic_stats = ['and_ones', 'assist_percentage', 'assists', 'assists_per_poss', 'block_percentage', 'blocking_fouls', 'blocks', 'blocks_per_poss', 'box_plus_minus', 'center_percentage', 'defensive_box_plus_minus', 'defensive_rebound_percentage', 'defensive_rebounds', 'defensive_rebounds_per_poss', 'defensive_win_shares', 'dunks', 'effective_field_goal_percentage', 'field_goal_attempts', 'field_goal_attempts_per_poss', 'field_goal_perc_sixteen_foot_plus_two_pointers', 'field_goal_perc_ten_to_sixteen_feet', 'field_goal_perc_three_to_ten_feet', 'field_goal_perc_zero_to_three_feet', 'field_goal_percentage', 'field_goals', 'field_goals_per_poss', 'free_throw_attempt_rate', 'free_throw_attempts', 'free_throw_attempts_per_poss', 'free_throw_percentage', 'free_throws', 'free_throws_per_poss', 'games_played', 'games_started', 'half_court_heaves', 'half_court_heaves_made', 'height', 'lost_ball_turnovers', 'minutes_played', 'nationality', 'net_plus_minus', 'offensive_box_plus_minus', 'offensive_fouls', 'offensive_rebound_percentage', 'offensive_rebounds', 'offensive_rebounds_per_poss', 'offensive_win_shares', 'on_court_plus_minus', 'other_turnovers', 'passing_turnovers', 'percentage_field_goals_as_dunks', 'percentage_of_three_pointers_from_corner', 'percentage_shots_three_pointers', 'percentage_shots_two_pointers', 'percentage_sixteen_foot_plus_two_pointers', 'percentage_ten_to_sixteen_footers', 'percentage_three_to_ten_footers', 'percentage_zero_to_three_footers', 'personal_fouls', 'personal_fouls_per_poss', 'player_efficiency_rating', 'player_id', 'point_guard_percentage', 'points', 'points_per_poss', 'points_generated_by_assists', 'position', 'power_forward_percentage', 'salary', 'shooting_distance', 'shooting_fouls', 'shooting_fouls_drawn', 'shooting_guard_percentage', 'shots_blocked', 'small_forward_percentage', 'steal_percentage', 'steals', 'steals_per_poss', 'take_fouls', 'team_abbreviation', 'three_point_attempt_rate', 'three_point_attempts', 'three_point_attempts_per_poss', 'three_point_percentage', 'three_point_shot_percentage_from_corner', 'three_pointers', 'three_pointers_assisted_percentage', 'three_pointers_per_poss', 'total_rebound_percentage', 'total_rebounds', 'total_rebounds_per_poss', 'true_shooting_percentage', 'turnover_percentage', 'turnovers', 'turnovers_per_poss', 'two_point_attempts', 'two_point_attempts_per_poss', 'two_point_percentage', 'two_pointers', 'two_pointers_per_poss', 'two_pointers_assisted_percentage', 'usage_percentage', 'value_over_replacement_player', 'weight', 'win_shares', 'win_shares_per_48_minutes']

basic_stats_selections=[{'label': k, 'value': k} for k in basic_stats]


from sportsipy.nba.roster import Roster

app.layout = html.Div([
    dcc.Dropdown(
        id="teams-dropdown",
        options=team_selections,
        placeholder="Select a team!"
    ),

    html.Hr(),

    dcc.Dropdown(id='player-dropdown'),

    dcc.Dropdown(
    id="stat-dropdown",
    options=basic_stats_selections,
    placeholder="Select a stat"
    ),

    html.Hr(),

    dcc.Graph(id="line-chart")
])

@app.callback(
    dash.dependencies.Output('player-dropdown', 'options'),
    [dash.dependencies.Input('teams-dropdown', 'value')])
def set_cities_options(selected_team):
    if selected_team is None:
        raise PreventUpdate
    else:
        player_list = [player.player_id for player in Roster("{}".format(selected_team)).players]
        player_selections = [{'label': k, 'value': k} for k in player_list]
        return player_selections


@app.callback(
    dash.dependencies.Output('stat-dropdown', 'options'),
    [dash.dependencies.Input('player-dropdown', 'options')])
def set_cities_value(selected_player):
    if selected_player is None:
        raise PreventUpdate
    else:
        player_id = selected_player[0]['value']
        player = Player("{}".format(player_id))
        player_df = player.dataframe
        player_df.replace(to_replace=[None], value=0, inplace=True)
        player_df = player_df[player_df["games_played"] > 0]
        player_df = player_df[player_df["games_played"] <= 82]
        value = player_df.to_dict('records')
        return value

@app.callback(
    dash.dependencies.Output('stat-dropdown', 'value'),
    [dash.dependencies.Input('stat-dropdown', 'options')])
def set_stat_value(value):
    if value is None:
        raise PreventUpdate
    else:
        try:
            stat = value[0]['label']
            player_df = pd.DataFrame(value)
            player_stat = player_df["{}".format(stat)]
            player_stat_dict = player_stat.to_dict('records')
            return player_stat_dict
        
        except KeyError:
            return dash.no_update

@app.callback(
    dash.dependencies.Output("line-chart", "figure"),
    [dash.dependencies.Input('teams-dropdown', 'value'),
     dash.dependencies.Input('player-dropdown', 'value'),
     dash.dependencies.Input("stat-dropdown", "value")])
     
def player_career_stats_graph(player, value, stat):
    """Pull data from sportsref and returns line chart of players career stats by year
    Args:
        value: stat to display
    """
    if value is None:
        raise PreventUpdate
    else:
        try:
            player_df = pd.DataFrame(value)
            player_career_stats_graph = px.line(
                            data_frame=player_df,
                            x=player_df.index.get_level_values(0),
                            y="{}".format(value),
                            title="{} over career".format(value)
            )
            return player_career_stats_graph
    
        except KeyError:
            return dash.no_update

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

That is the code I have and am stuck on how to solve this problem. Any help is greatly appreciated

Hi @nossyd

Check the formula:

player_list = player.player_id for player in Roster("{}".format(selected_team)).players]

I tryed to print the result using print(player_list) and it prints nothing :thinking:

Hi @nossyd

For some reason the player_list took a lot to be printed, finally I see the output:

[{'label': Luke Kennard (kennalu01), 'value': Luke Kennard (kennalu01)}, {'label': Ivica Zubac (zubaciv01), 'value': Ivica Zubac (zubaciv01)}, {'label': Serge Ibaka (ibakase01), 'value': Serge Ibaka (ibakase01)}, {'label': Nicolas Batum (batumni01), 'value': Nicolas Batum (batumni01)}, {'label': Lou Williams (willilo02), 'value': Lou Williams (willilo02)}, {'label': Reggie Jackson (jacksre01), 'value': Reggie Jackson (jacksre01)}, {'label': Terance Mann (mannte01), 'value': Terance Mann (mannte01)}, {'label': Kawhi Leonard (leonaka01), 'value': Kawhi Leonard (leonaka01)}, {'label': Paul George (georgpa01), 'value': Paul George (georgpa01)}, {'label': Marcus Morris (morrima03), 'value': Marcus Morris (morrima03)}, {'label': Patrick Beverley (beverpa01), 'value': Patrick Beverley (beverpa01)}, {'label': Amir Coffey (coffeam01), 'value': Amir Coffey (coffeam01)}, {'label': Mfiondu Kabengele (kabenmf01), 'value': Mfiondu Kabengele (kabenmf01)}, {'label': Daniel Oturu (oturuda01), 'value': Daniel Oturu (oturuda01)}, {'label': Patrick Patterson (pattepa01), 'value': Patrick Patterson (pattepa01)}, {'label': Jay Scrubb (scrubja01), 'value': Jay Scrubb (scrubja01)}]

You need to put the name of the players between " " or ’ ’ in the label and value options.

@Eduardo Thanks very much for looking into this problem for me! I was able to solve the problem by taking out two middle callbacks and doing the data preprocessing in the final app callback. I believe this helped so that I am not passing data around and put the data preprocessing in the final callback with the values obtained from the dropdown menus.

1 Like

No entendi nada, pero si funciona esta bien. jaja.