将第二个图表添加到 Dash app.layout 的问题
Posted
技术标签:
【中文标题】将第二个图表添加到 Dash app.layout 的问题【英文标题】:Issue adding second Graph into Dash app.layout 【发布时间】:2021-10-12 07:17:05 【问题描述】:下面的代码将运行并显示127.0.0.1
地址中的图形,但只有第一个图形正确显示。第二个图是一个 scatter_mapbox,它显示了根据用户选择的卧室数量过滤的给定县的价格。
电流输出:
第二张图应该是这样的:
app.layout = html.Div([
html.Div([
# Stuff that will be going on the top of the page
html.H1('King County Housing Data/Graphs'), # Heading 1
]),
html.Div([
html.H5('King County sqft-living / price Plot: 1900-2015'),
dcc.Dropdown(id='grade-selector',
options=['label': i, 'value': i for i in df['grade'].unique()],
value=7, # Default Value
multi=False, # Does not allow you to select multiple grades
style='width': '40%'), # Styling of the dropdown
html.Div(id='output-container'), # Callbacks Output #1
dcc.Graph(id='grade-price') # Callback's Output #2
]),
# Interactive Graph using a map
html.Div([
html.H5('Geospatial heatmap of King County: 1900-2015'),
dcc.Dropdown(id='Number-Of-Bedrooms',
options=['label': b, 'value': b for b in df['bedrooms'].unique()],
value=2,
multi=False,
style='width': '30%',
),
html.Div(),
dcc.Graph(id='bedrooms-selector')
])
])
# ----------------------------------------------------------------------------------------------------------------------
# App Callback & Function for Scatter Plot
@app.callback(
[Output(component_id='output-container', component_property='children'), # Outputs the html.Div
Output(component_id='grade-price', component_property='figure')], # Calls the graph dcc.Graph
[Input(component_id='grade-selector', component_property='value')] # Takes the input you put in with the
# dcc.Dropdown and passes it into the Output
)
def gupdate_output_div(grade_selector): # Makes the graph function
container = 'The grade the user selected was '.format(grade_selector) # Prints out the grade the user selected
dff = df.copy() # Makes a copy of the DataFrame, best practice
dff = dff[dff['grade'] == grade_selector] # Selects the grade that the user inputs
# Creates the Plotly Graph
fig = px.scatter(dff, x='sqft_living', y='price', marginal_y='violin', marginal_x='box', trendline='ols',
template='ggplot2')
return [container, fig]
# ----------------------------------------------------------------------------------------------------------------------
# App Callback & Function for Map
@app.callback(
[Output(component_id='bedrooms-selector', component_property='figure'),
Input(component_id='Number-Of-Bedrooms', component_property='value')])
def update_output_div1(bedroomFilter):
dff = df.copy() # Makes a copy of the DataFrame, best practice
dff = dff[dff['bedrooms'] == bedroomFilter] # Selects the number of bedrooms
color_by = 'price' # Setting the scale for teh price
color_upper = dff['price'].quantile(.05) # Excluding the bottom .05%
color_lower = dff['price'].quantile(.95) # Excluding the top .05%
fig = px.scatter_mapbox(dff, lat="lat", lon="lon",
animation_frame="decade",
# animation_group="country",
hover_name="price", hover_data=['price'],
color_continuous_scale=px.colors.sequential.Viridis,
color=color_by, range_color=[color_lower, color_upper],
opacity=0.4,
zoom=8.5, height=600)
fig.update_layout(mapbox_style="open-street-map")
fig.update_geos(fitbounds="locations")
fig.update_layout(
title=
'text': "Housing Price",
'y': 1,
'x': 0.5,
'xanchor': 'center',
'yanchor': 'auto',
legend=dict(
title="Home Price",
orientation="h",
yanchor="top")
)
return fig
if __name__ == '__main__':
app.run_server(debug=False, host='127.0.0.1')
数据:
price sqft_living grade bedrooms decade
0 13.180632 7.501082 7 5 1900
1 13.515081 8.384804 8 3 1900
2 13.345507 7.306531 7 2 1900
3 13.296317 7.319865 7 2 1900
4 13.091904 7.244228 7 4 1900
... ... ... ... ...
21603 14.253765 8.169053 9 3 2010
21604 12.345835 6.946976 9 3 2010
21605 13.233905 7.408531 8 2 2010
21606 12.873774 7.365180 8 3 2010
21607 14.346139 8.281471 11 4 2010
【问题讨论】:
【参考方案1】:主要问题是您的第二个回调的语法:
@app.callback(
[
Output(component_id="bedrooms-selector", component_property="figure"),
Input(component_id="Number-Of-Bedrooms", component_property="value"),
]
)
def update_output_div1(bedroomFilter):
# ...
return fig
这给出了:
dash.exceptions.InvalidCallbackReturnValue:回调 ..bedrooms-selector.figure.. 是一个多输出。 期望输出类型是列表或元组,但得到了 Figure...
删除Output
和Input
周围的列表。
所以改为这样做:
@app.callback(
Output(component_id="bedrooms-selector", component_property="figure"),
Input(component_id="Number-Of-Bedrooms", component_property="value"),
)
def update_output_div1(bedroomFilter):
# ...
return fig
如果您随后运行该应用程序并从第二个下拉列表中选择一个值,则会显示地图。
【讨论】:
非常感谢您的帮助!所以回调需要[]的唯一时间是回调中有多个输出时?在我的第一个回调中,我需要 [ ]。 不,这甚至没有必要。你也可以为所有回调省略[]
,但是你会返回一个元组而不是一个列表:return output_val1
、output_val2
而不是return [output_val1, output_val2]
。重要的部分是输入、输出和状态不在同一个列表中。以上是关于将第二个图表添加到 Dash app.layout 的问题的主要内容,如果未能解决你的问题,请参考以下文章
将第二个 UIToolbar 添加到 UITableViewController