Dropdown menu is not working

Hi guys, I managed to create a dropdown menu, but when I try to select something, I cannot see any values.

I created a list of cities: cities = np.random.choice([‘Frankfurt’, ‘München’, ‘Berlin’], size=num_apartments)

This is my code for the dropdown menu:

And here is the dashboard:

Does anyone have an idea what I am doing wrong?

Hey,
I would say from the screenshot, that ‘City’ is not in df_multi.columns, but without seeing more of your code it’s hard to say.

Hi,
I didn’t want to post the whole code because it is too long, but here is the df_multi part. So I’ve included ‘City’ there.

Generating data for multiple apartments

np.random.seed(42)
num_apartments = 300
cities = np.random.choice([‘Frankfurt’, ‘München’, ‘Berlin’], size=num_apartments)
districts = {
‘Frankfurt’: np.random.choice([‘Westend’, ‘Ostend’], size=num_apartments),
‘München’: np.random.choice([‘Altstadt’, ‘Bogenhausen’], size=num_apartments),
‘Berlin’: np.random.choice([‘Friedrichshain’, ‘Berlin-Mitte’], size=num_apartments)
}
room_types = np.random.choice([‘Room’, ‘Flat’, ‘House’], size=num_apartments)
num_bedrooms = np.random.randint(1, 6, size=num_apartments)
num_bathrooms = np.random.randint(1, 4, size=num_apartments)
num_beds = np.random.randint(1, 6, size=num_apartments)

Create a DataFrame for the new variables

data_multi = {
‘City’: cities,
‘District’: [districts[city][i] for i, city in enumerate(cities)],
‘Room_Type’: room_types,
‘Num_Bedrooms’: num_bedrooms,
‘Num_Bathrooms’: num_bathrooms,
‘Num_Beds’: num_beds,
}
df_multi = pd.DataFrame(data_multi)

Add baseline rent variations based on city and district

baseline_rents = {
(‘Frankfurt’, ‘Westend’): 100,
(‘Frankfurt’, ‘Ostend’): 120,
(‘München’, ‘Bogenhausen’): 140,
(‘München’, ‘Altstadt’): 160,
(‘Berlin’, ‘Friedrichshain’): 180,
(‘Berlin’, ‘Berlin-Mitte’): 200,
}
df_multi[‘Base_Rent’] = [baseline_rents.get((city, district), 100) for city, district in zip(df_multi[‘City’], df_multi[‘District’])]
df_multi[‘Daily_Rent’] = (
df_multi[‘Base_Rent’]
+ 50 * df_multi[‘Num_Bedrooms’]
+ 20 * df_multi[‘Num_Bathrooms’]
+ 30 * df_multi[‘Num_Beds’]
+ np.where(df_multi[‘Room_Type’] == ‘Flat’, 50, 0)
+ np.where(df_multi[‘Room_Type’] == ‘House’, 100, 0)
)

Convert categorical variables to dummy variables

df_multi = pd.get_dummies(df_multi, columns=[‘City’, ‘District’, ‘Room_Type’], drop_first=True)

df_multi = pd.get_dummies(df_multi, columns=['City', 'District', 'Room_Type'], drop_first=True)

This line actually deletes the City column,
I also get a KeyError: ‘City’

Do you know what I need to change there? Because if I simply delete it, I get multiple errors.
And it is weird because I don’t get an error with my code.

Hi @Jonajdjz ,

Try to change value of drop_first to False,

df_multi = pd.get_dummies(df_multi, columns=['City', 'District', 'Room_Type'], drop_first=False)

By changing drop_first=False, it will avoid to remove the City column from your data frame.

And hopefully your Dropdown can work properly.

1 Like

Hi @farispriadi ,

thank you very much for your help. Unfortunately, the dropdown is still not working :confused:

Hey @Jonajdjz,

Welcome to Plotly Community!

Could you please share a minimal reproducible version of your code in a more readable format so that we can help you more conveniently. You can command/ctrl+e your code snippet to make it more readable (i.e. pre-formatted text)

Cheers!

1 Like

Hi @Berbere,

thank you! So this is my code for now. thank you all for you support!

from dash import dcc
from dash import html
import dash_html_components as html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression

# Generating data for multiple apartments
np.random.seed(42)
num_apartments = 300
cities = np.random.choice(['Frankfurt', 'München', 'Berlin'], size=num_apartments)
districts = {
    'Frankfurt': np.random.choice(['Westend', 'Ostend'], size=num_apartments),
    'München': np.random.choice(['Altstadt', 'Bogenhausen'], size=num_apartments),
    'Berlin': np.random.choice(['Friedrichshain', 'Berlin-Mitte'], size=num_apartments)
}
room_types = np.random.choice(['Room', 'Flat', 'House'], size=num_apartments)
num_bedrooms = np.random.randint(1, 6, size=num_apartments)
num_bathrooms = np.random.randint(1, 4, size=num_apartments)
num_beds = np.random.randint(1, 6, size=num_apartments)

# Create a DataFrame for the new variables
data_multi = {
    'City': cities,
    'District': [districts[city][i] for i, city in enumerate(cities)],
    'Room_Type': room_types,
    'Num_Bedrooms': num_bedrooms,
    'Num_Bathrooms': num_bathrooms,
    'Num_Beds': num_beds,
}
df_multi = pd.DataFrame(data_multi)

# Add baseline rent variations based on city and district
baseline_rents = {
    ('Frankfurt', 'Westend'): 100,
    ('Frankfurt', 'Ostend'): 120,
    ('München', 'Bogenhausen'): 140,
    ('München', 'Altstadt'): 160,
    ('Berlin', 'Friedrichshain'): 180,
    ('Berlin', 'Berlin-Mitte'): 200,
}
df_multi['Base_Rent'] = [baseline_rents.get((city, district), 100) for city, district in zip(df_multi['City'], df_multi['District'])]
df_multi['Daily_Rent'] = (
    df_multi['Base_Rent']
    + 50 * df_multi['Num_Bedrooms']
    + 20 * df_multi['Num_Bathrooms']
    + 30 * df_multi['Num_Beds']
    + np.where(df_multi['Room_Type'] == 'Flat', 50, 0)
    + np.where(df_multi['Room_Type'] == 'House', 100, 0)
)

# Convert categorical variables to dummy variables
df_multi = pd.get_dummies(df_multi, columns=['City', 'District', 'Room_Type'], drop_first=False)

# Reshape the data for scikit-learn
features_multi = df_multi.drop(columns=['Base_Rent', 'Daily_Rent']).values
daily_rent_multi = df_multi['Daily_Rent'].values

# Create a linear regression model for multiple apartments
model_multi = LinearRegression()
model_multi.fit(features_multi, daily_rent_multi)

# Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

# App layout
app.layout = dbc.Container(
    [
        html.H1("Linear Regression Dashboard", className="display-4"),

        dbc.Row([
            dbc.Col([
                html.Label("City:"),
                dcc.Dropdown(
                    id='city-dropdown',
                    options=[{'label': city, 'value': city} for city in
                             df_multi['City'].unique()] if 'City' in df_multi.columns else [],
                    value=df_multi['City'].iloc[0] if 'City' in df_multi.columns and not df_multi[
                        'City'].empty else None,
                    className="form-select"
                ),
            ], className="mb-3"),
        ]),

        dbc.Row([
            dbc.Col([
                html.Label("District:"),
                dcc.Dropdown(
                    id='district-dropdown',
                    options=[{'label': district, 'value': district} for district in
                             df_multi['District'].unique()] if 'District' in df_multi.columns else [],
                    value=df_multi[df_multi['City'] == df_multi['City'].unique()[0]]['District'].unique()[
                        0] if 'District' in df_multi.columns else None,
                    className="form-select"
                ),
            ], className="mb-3"),
        ]),

        dbc.Row([
            dbc.Col([
                html.Label("Room Type:"),
                dcc.Dropdown(
                    id='room-type-dropdown',
                    options=[{'label': room_type, 'value': room_type} for room_type in
                             df_multi['Room_Type'].unique()] if 'Room_Type' in df_multi.columns else [],
                    value=df_multi['Room_Type'].iloc[0] if 'Room_Type' in df_multi.columns and not df_multi[
                        'Room_Type'].empty else None,
                    className="form-select"
                ),
            ], className="mb-3"),
        ]),

        dbc.Row([
            dbc.Col([
                html.Label("Number of Bedrooms:"),
                dcc.Input(id='num-bedrooms-input', type='number', value=1, className="form-control"),
            ], className="mb-3"),
        ]),

        dbc.Row([
            dbc.Col([
                html.Label("Number of Bathrooms:"),
                dcc.Input(id='num-bathrooms-input', type='number', value=1, className="form-control"),
            ], className="mb-3"),
        ]),

        dbc.Row([
            dbc.Col([
                html.Label("Number of Beds:"),
                dcc.Input(id='num-beds-input', type='number', value=1, className="form-control"),
            ], className="mb-3"),
        ]),

        html.Hr(),  # Add a horizontal line for visual separation

        html.Div([
            html.H3("Predicted Daily Rent:", className="display-5"),
            html.Div(id='output-container', className="lead"),
        ], className="mb-4"),

    ],
    fluid=True
)


from dash.exceptions import PreventUpdate

# Callback to update the district dropdown options based on the selected city
@app.callback(
    Output('district-dropdown', 'options'),
    [Input('city-dropdown', 'value')]
)
def update_district_options(selected_city):
    if 'City' in df_multi.columns and 'District' in df_multi.columns:
        # Check if there are any cities in the dataset
        if df_multi['City'].empty:
            raise PreventUpdate

        # Check if the selected_city exists in the dataset
        if selected_city and selected_city not in df_multi['City'].unique():
            raise PreventUpdate

        # Filter districts based on the selected city
        districts_for_city = df_multi[df_multi['City'] == selected_city]['District'].unique()
        options = [{'label': district, 'value': district} for district in districts_for_city]
        if not options:
            raise PreventUpdate
        return options
    else:
        raise PreventUpdate



# Callback to update the room type dropdown options based on the selected district
@app.callback(
    Output('room-type-dropdown', 'options'),
    [Input('district-dropdown', 'value')]
)
def update_room_type_options(selected_district):
    return [{'label': room_type, 'value': room_type} for room_type in
            df_multi[df_multi['District'] == selected_district]['Room_Type'].unique()] if 'Room_Type' in df_multi.columns else []


# Callback to update the output based on input values
@app.callback(
    Output('output-container', 'children'),
    [Input('city-dropdown', 'value'),
     Input('district-dropdown', 'value'),
     Input('room-type-dropdown', 'value'),
     Input('num-bedrooms-input', 'value'),
     Input('num-bathrooms-input', 'value'),
     Input('num-beds-input', 'value')]
)
def update_output(selected_city, selected_district, selected_room_type, num_bedrooms, num_bathrooms, num_beds):
    # Handle the case when City, District, or Room Type dropdowns are not available
    if 'City' not in df_multi.columns or 'District' not in df_multi.columns or 'Room_Type' not in df_multi.columns:
        return "Please choose a valid combination of City, District, and Room Type."

    # Handle the case when selected_district is None
    if selected_district is None:
        return "Please choose a valid District."

    # Create a dictionary with input values
    input_data = {
        'City': selected_city,
        'District': selected_district,
        'Room_Type': selected_room_type,
        'Num_Bedrooms': num_bedrooms,
        'Num_Bathrooms': num_bathrooms,
        'Num_Beds': num_beds,
    }

    # Create a DataFrame for the input values
    input_df = pd.DataFrame([input_data])

    # Convert categorical variables to dummy variables
    input_df = pd.get_dummies(input_df, columns=['City', 'District', 'Room_Type'], drop_first=True)

    # Predict daily rent using the model
    predicted_daily_rent = model_multi.predict(input_df.values)[0]

    # Display the predicted daily rent
    return f"Predicted Daily Rent: {predicted_daily_rent:.2f} €"


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

Hi @Jonajdjz ,

I think I found the problem.

The problem is using df_multi to set options and value in Dropdown.

Because you use df_multi and convert to dummy variables, you need to keep original df_multi dataframe by copying and put it before change to dummy variables (it will named df_multi_ori).

Just like code below.

...

# copy original df_multi before convert to dummy variable 
df_multi_ori = df_multi.copy()

# Convert categorical variables to dummy variables
df_multi = pd.get_dummies(df_multi, columns=['City', 'District', 'Room_Type'], drop_first=False)

...

After that you can update Dropdown code.
Change df_multi to df_multi_ori.

# App layout
app.layout = dbc.Container(
    [
        html.H1("Linear Regression Dashboard", className="display-4"),

        dbc.Row([
            dbc.Col([
                html.Label("City:"),
                dcc.Dropdown(
                    id='city-dropdown',
                    # change df_multi to df_multi_ori in options
                    options=[{'label': city, 'value': city} for city in
                             df_multi_ori['City'].unique()] if 'City' in df_multi_ori.columns else [],
                    # change df_multi to df_multi_ori in value
                    value=df_multi_ori['City'].iloc[0] if 'City' in df_multi_ori.columns and not df_multi_ori[
                        'City'].empty else None,
                    className="form-select"
                ),
            ], className="mb-3"),
        ]),

And I think you should do same thing for District and Room Type Dropdown.
Hope this help.

2 Likes

Perfect answer with a good recommendation @farispriadi

In other words, because of get_dummies() function, the line below, your df_multi does not have a columns called 'City' anymore but 'City_Frankfurt', 'City_München' for the respective city names etc… Yet, you try to use that column name as an option to your dropdown component.

Cheers to both!

2 Likes

@farispriadi you’re crazy man. Thank you so much!

1 Like