I'm trying to display a scatterplot with trend lines that also has a drop-down menu. I'm still learning Dash-Plotly and am having trouble debugging what I did wrong. I've used the dash tutorial and a lot of other StackOverflow posts but I'm not getting what I need to do. I thought I did all my callbacks correctly and set up my app.layout correctly.
My Code:
app.layout = html.Div([
html.H1('King County Housing Data: 1900-2015', style = {'text-align': 'center'}),
dcc.Dropdown(id='grade-selector', # geo-dropdown is what you'll see with the drop down
# Create a loop that pulls the unique values from the grade column and it values for the dropdown
options=[{'label': i, 'value': i} # Creates the unique properties for the dropdown
for i in df['grade'].unique()],
value=7,
multi = False,
style={'width', '40%'}), # value = default value for the dropdown)
html.Div(id='output-container'),
dcc.Graph(id='grade-price')
])
# Set up the callback functions: This is what connects all the figures and things together
@app.callback(
# A call back needs two things, a input and an output
[Output(component_id='output-container', component_property='children'),
Output(component_id='grade-price', component_property='figure')],
[Input(component_id='grade_selector', component_property='value')]
)
# Connecting Plotly graphs to Dash Components:
# **NOTE** Your arguments are tied to the number of inputs that you have. If you have only one input, then you'll
# Only have one argument.
def gupdate_output_div(grade_selector): # The argument refers to the Input's Component Property.
print(grade_selector)
print(type(grade_selector))
container = 'The grade the user selected was {}'.format(grade_selector)
# Creating a copy of the dataframe, not smart to mess around with the primary DataFrame in here
dff = df.copyy()
dff = dff[dff['grade']== grade_selector] # You are sorting the DF by what the user has selected
# Plotly Express:
fig = px.scatter(dff, x='sqft_living', y='price', color='view', marginal_y='violin',
marginal_x='box', trendline='ols', template='plotly_dark')
return container, fig # What you return here is actually going to go into the output!
# If you have two Outputs, you're returning two things, three Outputs --> three returns
if __name__ == '__main__':
app.run_server(debug=False)
My Data:
display(df[['price','sqft_living','grade']].head())
price sqft_living grade
0 13.180632 7.501082 7
1 13.515081 8.384804 8
2 13.345507 7.306531 7
3 13.296317 7.319865 7
4 13.091904 7.244228 7
The key issues are:
As @r-beginners mentioned, there is a typo in dff = df.copyy()
which should be replaced by dff = df.copy()
.
The id of the dropdown that you defined in the layout is 'grade-selector'
, but in the callback you are using 'grade_selector'
.
The style property of the dropdown is defined incorrectly as it needs to be a dictionary, i.e. you need to replace {'width', '40%'}
with {'width': '40%'}
.
You are using the 'view'
column to define the colorscale for the graph, but it's not clear if you actually have this column in your data frame (it's not included in the df
shown in your question above).
These issues have been fixed in the code below:
import pandas as pd
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import plotly.express as px
# data
df = pd.DataFrame({
'price': {0: 13.180632, 1: 13.515081, 2: 13.345507, 3: 13.296317, 4: 13.091904},
'sqft_living': {0: 7.501082, 1: 8.384804, 2: 7.306531, 3: 7.319865, 4: 7.244228},
'grade': {0: 7, 1: 8, 2: 7, 3: 7, 4: 7}
})
# app set-up
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
# app layout
app.layout = html.Div([
html.H1('King County Housing Data: 1900-2015', style={'text-align': 'center'}),
dcc.Dropdown(id='grade-selector',
options=[{'label': i, 'value': i} for i in df['grade'].unique()],
value=7,
multi=False,
style={'width': '40%'}),
html.Div(id='output-container'),
dcc.Graph(id='grade-price')
])
# app callbacks
@app.callback(
[Output(component_id='output-container', component_property='children'),
Output(component_id='grade-price', component_property='figure')],
[Input(component_id='grade-selector', component_property='value')]
)
def gupdate_output_div(grade_selector):
container = 'The grade the user selected was {}'.format(grade_selector)
dff = df.copy()
dff = dff[dff['grade'] == grade_selector]
fig = px.scatter(dff, x='sqft_living', y='price', marginal_y='violin', marginal_x='box', trendline='ols', template='plotly_dark')
return [container, fig]
if __name__ == '__main__':
app.run_server(debug=False, host='127.0.0.1')