plotly-dash: embed indicator graph inside of a dbc card - python

I have been banging my head off the wall all day and cannot find a way to fit a dash indicator inside of a dash_bootstrap_components card.
It seems that the body of the card and the graph do not live inside of the card. I am not very familiar with dash so it is difficult to find a way to solve the issue.
here is what I have been able to do so far in terms of plotting the indicator:
fig3 = go.Figure()
fig3.add_trace(go.Indicator(
mode = "number+delta",
number = {"font":{"size":40},'prefix': "$"},
value = 2045672,
delta = {'reference': 30000},
gauge = {'shape': "bullet"},
title = {"text": "On Hand<br><span style='font-size:0.9em;color:gray'></span>"},
#title='Stock On Hand',
domain = {'x': [0, 1], 'y': [0, 1]},
))
fig3.update_layout(paper_bgcolor = "rgba(0,0,0,0)",
plot_bgcolor = "rgba(0,0,0,0)",
autosize=False,
width = 200,
height=200,
)
fig3.update_traces(align="center", selector=dict(type='indicator'))
I am forced to specify width and height for the indicator otherwise it is way too big, however this cause issues because its size does not adjust in regards to the card.
here is the html dash code for the box and the plot:
html.Div(children=[
html.Div(children=[
html.Div(children=[
html.Div(children=[
dbc.Card(
[dbc.CardBody(
[dcc.Graph(figure=fig3)
]
)],className="card", style={"width": "15rem", "height":"8rem"}
),
], className='jumbotron', style={'background-color': '#fffffff'}),
])
],className="col-3 mx-auto"),
],className="row p-0 h-100", style={'background-color': '#f7f7f7', 'height':110}),
], className="full-width p-0 h-100", style={'background-color': '#fffffff'}),
and here is what the final output looks like:
I am not sure what else I can try to bring the graph inside of the box, any help would be appreciated

Remove the instances where you set the height in the style of dash components and the indicator doesn't get cut off.
So you can do something like this:
app.layout = html.Div(
children=[
html.Div(
children=[
html.Div(
children=[
html.Div(
children=[
dbc.Card(
[
dbc.CardBody(
[dcc.Graph(figure=fig3)],
style={"width": "15rem"},
)
]
)
],
className="jumbotron",
style={"backgroundColor": "#fffffff"},
)
],
className="col-3 mx-auto",
)
],
className="row p-0 h-100",
style={"backgroundColor": "#f7f7f7"},
)
],
className="full-width p-0 h-100",
style={"backgroundColor": "#fffffff"},
)
I've also changed the casing of the style properties to camelCase as this is what React (which dash uses) likes.

Related

How to make interactive map dashboard using geojson file

I want to make interactive dashboard using 'callback'. The final goal is to make dashboard graph to change when person click the polygon of the map. But i don't know how to make 'id' for each polygon.Can anybody help solving this problem? Below is the code.
for idx, sigun_dict in enumerate(state_geo1['features']):
sigun_id = sigun_dict['properties']['new_code']
sigun_nmm = df.loc[(df.new_code == sigun_id), 'SGG'].iloc[0]
A_R = df.loc[(df.new_code == sigun_id), 'A_R'].iloc[0]
txt = f'<b><h4>{sigun_nmm}</h4></b>A_R:{A_R}<br>'
state_geo1['features'][idx]['properties']['tooltip1'] = txt
import plotly.express as px
for Type in Types:
trace1.append(go.Choroplethmapbox(
geojson=state_geo1,
locations=df['new_code'].tolist(),
z=df[Type].tolist(),
text=suburbs,
featureidkey='properties.new_code',
colorscale=color_deep,
colorbar=dict(thickness=20, ticklen=3),
zmin=0,
zmax=df[Type].max() + 0.5,
visible=False,
subplot='mapbox1',
hovertemplate = "<b>%{text}</b><br><br>"+
"value: %{z}<br>"+
"<extra></extra>"))
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = "인구감소지역 지원방안"
app.layout = html.Div([
html.Div(children=[
html.H1(children='한국 인구감소지역 지원방안',
style={"fontSize":"48px"},
className="header-title"
),
html.P(
children="한국 인구감소지역의 대표 지표들과 지역에 따른 분포 지도",
className="header-description"
),
dcc.Graph(
id='example-graph-1',
figure=fig
),
html.Div(children='''
본 대시보드는 지방행정연구원의 지원으로 작성되었음
''')
]),
html.Div([
dash_table.DataTable(
id='datatable_id',
data=df.to_dict('records'),
columns=[
{"name":i, "id": i, "deletable":False, "selectable":False} for i in df.columns
],
editable=False,
filter_action="native",
sort_action="native",
sort_mode="multi",
row_selectable="multi",
row_deletable=False,
selected_rows=[],
page_action="native",
page_current=0,
page_size=6,
],
className='row'),
])
i want to make the graph to change when person click the polygon of the map. But don't know how to create the id for that.

Additional elements inline with Dash's dcc.Tabs?

For my Dash app, I want to create a navigation bar that has links to the different pages but also additional stuff, e.g. the currently logged in user, and logos and stuff.
However, I unfortunately cannot use pages (Like in the "Navbar" example in dbc) since the WebApp has to be hosted as a single-url app inside another tool. My only option is to got with dcc.Tabs.
However, it looks to me like dcc.Tabs forces a newline behind the Tabs. I tried different things to prevent that, but nothing seems to be working. The best I got so far is the example below. How do I make it so that the text is in the same row as the Tabs element?
tabs_styles = {
'height': '44px', "width": "49%", "display":"inline-block"
}
app.layout = html.Div(children=[
html.Div(children=[
dcc.Tabs(id="tabs-styled-with-inline", value='tab-1', children=[
dcc.Tab(label='Page1', value='tab-1', style=tab_style, selected_style=tab_selected_style),
dcc.Tab(label='Page2', value='tab-2', style=tab_style, selected_style=tab_selected_style),
], style=tabs_styles)]),
html.Span(children=[
" Logged in as ",
html.Strong(id="username")
], style = tabs_styles),
html.Div(children=[
# Distance to header:
html.Hr(),
html.Div(id='tabs-content-inline')
])
])
Your inline style should be applied to the parent div of your Tabs component. I made some small modifications here (look at tabs_container_styles):
tabs_styles = {"height": "44px"}
tabs_container_styles = {"width": "49%", "display": "inline-block"}
app.layout = html.Div(
children=[
html.Div(
children=[
dcc.Tabs(
id="tabs-styled-with-inline",
value="tab-1",
children=[
dcc.Tab(label="Page1", value="tab-1"),
dcc.Tab(label="Page2", value="tab-2"),
],
style=tabs_styles,
)
],
style=tabs_container_styles,
),
html.Span(
children=[" Logged in as ", html.Strong(id="username")], style=tabs_styles
),
html.Div(
children=[
# Distance to header:
html.Hr(),
html.Div(id="tabs-content-inline"),
]
),
]
)
Set the parent_style property of your Tabs component instead of the style property and move your Span component to be a child of the div containing your Tabs component.
parent_style (dict; optional): Appends (inline) styles to the top-level parent container holding both the Tabs container and the content container.
style (dict; optional): Appends (inline) styles to the Tabs container holding the individual Tab components.
https://dash.plotly.com/dash-core-components/tabs
MRE
from dash import Dash, html, dcc
tabs_styles = {"height": "44px", "width": "49%", "display": "inline-block"}
app = Dash()
app.layout = html.Div(
children=[
html.Div(
children=[
dcc.Tabs(
id="tabs-styled-with-inline",
value="tab-1",
children=[
dcc.Tab(
label="Page1", value="tab-1", style={}, selected_style={}
),
dcc.Tab(
label="Page2", value="tab-2", style={}, selected_style={}
),
],
parent_style=tabs_styles,
),
html.Span(
children=[" Logged in as ", html.Strong(id="username")], style=tabs_styles
),
]
),
html.Div(
children=[
# Distance to header:
html.Hr(),
html.Div(id="tabs-content-inline"),
]
),
]
)
if __name__ == "__main__":
app.run_server()

How to insert several dropdowns in plotly dash

I am trying to get into using Plotly Dash and I am getting stuck on this one piece where I would like to dynamically add a user-defined number of dropdowns. Here is what I tried:
# Import required libraries
import dash
import math
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
# App Begins
app = dash.Dash(
__name__, meta_tags=[{"name": "viewport", "content": "width=device-width"}],
)
app.title = "Tool"
server = app.server
# Create global chart template
mapbox_access_token = "pk.eyJ1IjoicGxvdGx5bWFwYm94IiwiYSI6ImNrOWJqb2F4djBnMjEzbG50amg0dnJieG4ifQ.Zme1-Uzoi75IaFbieBDl3A"
layout = dict(
autosize=True,
automargin=True,
margin=dict(l=30, r=30, b=20, t=40),
hovermode="closest",
plot_bgcolor="#F9F9F9",
paper_bgcolor="#F9F9F9",
legend=dict(font=dict(size=10), orientation="h"),
title="Satellite Overview",
mapbox=dict(
accesstoken=mapbox_access_token,
style="light",
center=dict(lon=-78.05, lat=42.54),
zoom=7,
),
)
# Create app layout
app.layout = html.Div(
[
dcc.Store(id="aggregate_data"),
# empty Div to trigger javascript file for graph resizing
html.Div(id="output-clientside"),
html.Div(
[
html.Div(
[
html.Img(
src=app.get_asset_url("dash-logo.png"),
id="plotly-image",
style={
"height": "60px",
"width": "auto",
"margin-bottom": "25px",
},
)
],
className="one-third column",
),
html.Div(
[
html.Div(
[
html.H3(
"Dash Tool",
style={"margin-bottom": "0px"},
),
]
)
],
className="one-half column",
id="title",
),
],
id="header",
className="row flex-display",
style={"margin-bottom": "25px"},
),
html.Div(
[
html.Div(
[
html.P("Quantity 1:", className="control_label"),
dcc.Input(
id="quantity_1",
type="number",
placeholder=33.
),
html.P("Quantity 2:", className="control_label"),
dcc.Input(
id="quantity_2",
type="number",
placeholder=-115.
),
html.P("Number of Drop Downs:", className="control_label"),
dcc.Slider(
id="drop_downs",
min=2,
max=10,
value=2,
step=1.0,
className="dcc_control",
),
html.P("Load Inputs:", className="control_label"),
dcc.Checklist(
id='sources_flag',
options=[
{'label': 'Yes', 'value': 'Y'},
],
value=['Y'],
labelStyle={'display': 'inline-block'}
),
html.Div(id='source_dropdown_container', children=[]),
html.Div(id='source_dropdown_container_output'),
html.Div(id='source_file_container', children=[]),
html.Div(id='source_file_container_output'),
],
className="pretty_container four columns",
id="cross-filter-options",
),
],
className="row flex-display",
),
],
id="mainContainer",
style={"display": "flex", "flex-direction": "column"},
)
# Create callbacks
#app.callback(
[
Output(component_id='source_dropdown_container_output', component_property='children'),
],
[
Input(component_id='drop_downs', component_property='value'),
Input(component_id='sources_flag', component_property='value'),
]
)
def update_source_dropdowns(value, value_1):
"""Controls the number of drop-downs available to choose sources"""
if value_1 == 'Y':
children = []
for i in range(0, value):
new_dropdown = dcc.Dropdown(
id=f'''source_dropdown_{str(i)}''',
options=['GOOG', 'FB', 'TDOC', 'FANG']
)
children.append(new_dropdown)
print(children)
print(type(children))
return children
I keep running into a callback error. The drop down is constructed properly, so I am kind of confused as to why that error is being invoked.
dash.exceptions.InvalidCallbackReturnValue: The callback ..source_dropdown_container_output.children.. is a multi-output.
Expected the output type to be a list or tuple but got:
None.
Any guidance or help is appreciated. All I am trying to do is add based on user input a dynamic number of drop downs to the layout.
you have three errors in your callback
there is only one return, hence do not define Output as a list
conditional check is wrong, should be if value_1 == ['Y']:
doc.Dropdown() options argument needs to define list of dict
# Create callbacks
#app.callback(
Output(component_id='source_dropdown_container_output', component_property='children'),
[
Input(component_id='drop_downs', component_property='value'),
Input(component_id='sources_flag', component_property='value'),
]
)
def update_source_dropdowns(value, value_1):
"""Controls the number of drop-downs available to choose sources"""
print("cb", value, value_1)
if value_1 == ['Y']:
children = []
for i in range(0, value):
new_dropdown = dcc.Dropdown(
id=f'''source_dropdown_{str(i)}''',
options=[{"label":v, "value":v } for v in ['GOOG', 'FB', 'TDOC', 'FANG']],
)
children.append(new_dropdown)
print(children)
print(type(children))
return children

Non-responsive scatter/bar plots to the Callback function

I am very new to Plotly Dash and I cannot get a hang of the #callback function with multiple inputs linked to two (scatter/bar) graphs.
Dashboard
Sample Data
For some reason, after selecting the inputs and clicking the “Run selection” button, the graphs do not update accordingly. Does anyone know what I am doing wrong? Been reading the documentation and browsing through online examples, but could not figure this one out... I believe something is wrong with the #callback function or the way I defined the data in my function.
Thank you in advance, would highly appreciate every bit of help! :slight_smile:
import pandas as pd
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import plotly.graph_objs as go
import plotly.express as px
# load the data
data = pd.read_excel('example_data.xlsx')
data.fillna(0, inplace=True)
data['Satellite'] = data['Satellite'].astype(int)
#initiate app and set theme
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
# navigation bar
navbar = dbc.NavbarSimple(
children=[
dbc.NavItem(dbc.NavLink("Page 1", href="#")),
dbc.DropdownMenu(
children=[
dbc.DropdownMenuItem("Page 2", href="#"),
dbc.DropdownMenuItem("Page 3", href="#"),
],
nav=True,
in_navbar=True,
label="More",
),
],
brand="Sample Dash Application",
brand_href="#",
color="primary",
dark=True,
)
# Construct a dictionary of dropdown values for the days
day_options = []
for day in data['AsofDate'].unique():
# grab day_options and append to it
day_options.append({'label':str(day),'value':day})
# Construct a dictionary of dropdown values for the portfolios
portfolio_options = []
for portfolio in data['Satellite'].unique():
portfolio_options.append({'label':str(portfolio),'value':int(portfolio) or 0})
# Construct a dictionary of dropdown values for the region
region_options = []
for region in data['Region'].unique():
region_options.append({'label':str(region),'value':region})
###############################################################################
# Filter pane
# Check dash core components at https://dash.plotly.com/dash-core-components
###############################################################################
controls = [
html.Div(
[
'Select Day',
dcc.Dropdown(
id='day-dropdown',
options=day_options,
value=data['AsofDate'].min(),
clearable=False
),
]
),
html.Div(
[
'Select Portfolio',
dcc.Dropdown(
id='portfolio-dropdown',
options=portfolio_options,
value=data['Satellite'].min(),
clearable=False
),
]
),
html.Div(
[
'Select Region',
dcc.Dropdown(
id='region-dropdown',
options=region_options,
value=data['Region'].min(),
clearable=False
),
]
),
html.Br(),
dbc.Button("Run selection", color="primary", id="button-submit")
]
###############################################################################
# Add components here, e.g. graphs
###############################################################################
avp_graph = dcc.Graph(id="avp-graph", style={"height": "500px"})
bar_plot_graph = dcc.Graph(id='bar-plot-graph', style={"height": "500px"})
###############################################################################
# Container
# Check dash core components at https://dash.plotly.com/dash-core-components
###############################################################################
container = dbc.Container(
fluid=True,
children=[
html.Hr(),
html.H3('Dashboard'),
html.Hr(),
# Bootstrap Layout examples:
# https://getbootstrap.com/docs/4.0/examples/
# Bootstrap grid system: https://getbootstrap.com/docs/4.0/layout/grid/
# Under each column (2, 5, 5) you can add components.
# The left column has a width of 2 and contains the controls only.
# The middle column has a width of 5 and contains a table and a graph.
# The right column has a width of 5 and contains a table and a graph.
dbc.Row(
[
dbc.Col(
[
# See https://dash-bootstrap-components.opensource.faculty.ai/docs/components/card/
dbc.Card([
dbc.CardHeader("Filter Pane"),
dbc.CardBody(controls),
]
),
],
sm=2
),
dbc.Col(
[
html.H5('Column 1'),
avp_graph # middle column, graph 1
],
sm=5
),
dbc.Col(
[
html.H5('Column 2'),
bar_plot_graph # right column, graph 2
],
sm=5
)
]
)
]
)
# Define Layout
app.layout = html.Div([
navbar,
container
])
#app.callback(
[
Output("avp-graph", "figure"),
Output("bar-plot-graph", "figure")
],
[Input("button-submit", "n_clicks")],
[
State("day-dropdown", "value"),
State("portfolio-dropdown", "value"),
State("region-dropdown", "value"),
],
)
def run_submit(n_clicks, day, portfolio, region):
# Bar plot
mask = data["AsofDate"] == day
bar_plot_graph = px.bar(data[mask], x=data['Region'], y=data['Return'], title='Bar Plot') # barmode="group",
# Scatter Plot
avp_graph = px.scatter(
x=data['line_x'],
y=data['line_y'],
labels={"x": "x", "y": "y"},
title=f"Scatter Plot",
)
return [avp_graph, bar_plot_graph] # return the components in the order of Output Callbacks!!!
if __name__ == '__main__':
app.run_server(port=8051, debug=False)
I'm not sure how you want your plots to change, but what I can see is:
The variables portfolio and region are defined by the state of the dropdown menus, but they are not used in your callback function.
The plot avp_graph in the callback function doesn't depend on any input. Therefore, it makes sense that it remains constant independently of what you select in your dropdown menus.
The plot bar_plot_graph only depends on the variable day.

dash plotly bootstrap number input placing

So I want to place my text box as shown
However, my code doesn't work and show me this instead
Heres my coding:
html.H1("Query1", style={'text-align': 'center','fontSize': 30}),
dbc.Row(
[
dbc.Col(dcc.Graph(id='graphQ', figure={}),md=8),
html.P("1"),
dbc.Col(dbc.Input(type="number", min=0, max=10, step=1),),
html.P("2"),
dbc.Col(dbc.Input(type="number", min=0, max=10, step=1)),
]),
dbc.Row(
[
html.P("1"),
dbc.Col(dbc.Input(type="number", min=0, max=10, step=1),),
html.P("2"),
dbc.Col(dbc.Input(type="number", min=0, max=10, step=1),)],
align="end",
)
])]))
Any help is appreciated!
You could do something like this:
def custom_input(paragraph_text, min_value=0, max_value=10, step=1):
return html.Div(
children=[
html.P(paragraph_text, style={"paddingRight": 10}),
dbc.Input(type="number", min=min_value, max=max_value, step=step),
],
style={"display": "flex"},
)
app.layout = html.Div(
children=[
html.H1("Query1", style={"textAlign": "center", "fontSize": 30}),
dbc.Row(
[
dbc.Col(dcc.Graph(id="graphQ", figure={}), md=8),
dbc.Col(
children=[
dbc.Row(
[
dbc.Col(custom_input("1")),
dbc.Col(custom_input("2")),
],
style={"paddingBottom": 30},
),
dbc.Row(
[
dbc.Col(custom_input("1")),
dbc.Col(custom_input("2")),
],
style={"paddingBottom": 30},
),
],
md=4,
),
]
),
]
)
I've abstracted your label / input component combination into a custom function to hopefully make the layout approach more clear and the code more reusable.
So my idea here is we only need one row with two columns. Where the first column consists of the entire graph.
The second column consists of two rows where each row contains two columns, each containing a custom input.

Categories

Resources