Plotly Dash callback function doesn't work - python

I am learning Dash and wanted to create a dashboard with a dropdown connected to a chart, but it doesn't work. The chart does not fill with data somehow and I get an empty dashboard with a dropdown that does nothing.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd
df = pd.read_csv('gapminderDataFiveYear.csv')
app = dash.Dash()
year_options = []
for year in df['year'].unique():
year_options.append({'label':str(year), 'value':year})
app.layout = html.Div([
dcc.Graph(id='graph'),
dcc.Dropdown(id='year picker', options=year_options,
value=df['year'].min())
])
#app.callback(Output('graph','figure'),
[Input('year-picker', 'value')])
def update_figure(selected_year):
filtered_df = df[df['year']==selected_year]
traces = []
for continent_name in filtered_df['continent'].unique():
df_by_continent = filtered_df[filtered_df['continent']==continent_name]
traces.append(go.Scatter(
x = df_by_continent['gdpPercap'],
y= df_by_continent['lifeExp'],
mode='markers',
opacity=0.7,
marker = {'size':15},
name = continent_name
))
return {'data':traces,'layout':go.Layout(title='My Plot', xaxis={'title':'GDP Per Cap', 'type':'log'},yaxis={'title':'Life Expectancy'})}
if __name__== '__main__':
app.run_server()

Related

Plotly Dash - callback dash table on python doesnt trigger

I have an app with multiple pages, controlled from this index, in a new page I want to insert a dash table and assign some interactivity using callbacks. Take a basic dash table example (https://dash.plotly.com/datatable) and insert it into my app, but the callback doesn't get executed. The only thing that changes when inserting into my app, is the way I create the app.layout, which is created from a function.
The table is created but the callback doesn't trigger.
Index.py
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
from homepage import Homepage
from resumen_comunal import Resumen_Comunal
from dash_main_table import main_Table
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.FLATLY])
app.config.suppress_callback_exceptions = True
app.layout = html.Div([
dcc.Location(id = 'url', refresh = False),
html.Div(id = 'page-content')
])
#app.callback(dash.dependencies.Output('page-content', 'children'),
[dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/Cobertura_CV':
return Resumen_Comunal()
if pathname == '/Gestion_CV':
return main_Table()
else:
return Homepage()
if __name__ == '__main__':
app.run_server(debug=False)
dash_table.py
import dash
from dash import Dash, dash_table, dcc, html
from dash.dependencies import Input, Output
import pandas as pd
import dash_bootstrap_components as dbc
from navbar import Navbar
nav = Navbar()
app = dash.Dash(__name__, external_stylesheets = [dbc.themes.FLATLY])
df = pd.read_csv('https://git.io/Juf1t')
body = dbc.Container([
dbc.Label('Click a cell in the table:'),
dash_table.DataTable(df.to_dict('records'),[{"name": i, "id": i} for i in df.columns], id='tbl'),
dbc.Alert(id='tbl_out'),
])
#app.callback(Output('tbl_out', 'children'),
Input('tbl', 'active_cell'))
def update_graphs(active_cell):
return str(active_cell) if active_cell else "Click the table"
def main_Table():
layout = html.Div([
nav,
body
])
return layout
if __name__ == "__main__":
app.run_server(debug=True)
Thanks for your help!
So, the callback is not triggered because you’re trying to populate the dash table in a separate application while the callback for the same is created inside a different application.
You don't have to create a new app object given that it's already created in index.py and the layout is passed to that same app object
Here's what you should do inside dash_table.py
import dash
from dash import Dash, dash_table, dcc, html,callback
from dash.dependencies import Input, Output
import pandas as pd
import dash_bootstrap_components as dbc
from navbar import Navbar
nav = Navbar()
df = pd.read_csv('https://git.io/Juf1t')
body = dbc.Container([
dbc.Label('Click a cell in the table:'),
dash_table.DataTable(df.to_dict('records'),[{"name": i, "id": i} for i in df.columns], id='tbl'),
dbc.Alert(id='tbl_out'),
])
#callback(Output('tbl_out', 'children'),
Input('tbl', 'active_cell'))
def update_graphs(active_cell):
print(active_cell)
return str(active_cell) if active_cell else "Click the table"
def main_Table():
layout = html.Div([
nav,
body
])
return layout

Plotly Dash dcc.Interval fails after a while: Callback error updating graph.figure

I'm trying to set my Dash app to automatically pull the latest data from a .csv file used in the data frame with dcc.Interval. The error code isn't providing a detailed explanation and also doesn't always appear. I've tried this with both a button and a set 6 sec interval, but the result seems to be the same. The Dash app runs fine at first and refreshes fine a few times, then error starts occurring:
Callback error updating graph.figure
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
app = dash.Dash(__name__)
server = app.server
df = pd.read_csv('example.csv', encoding="WINDOWS-1252")
app.layout = html.Div([
dcc.Graph(id='graph'),
dcc.Interval(
id='interval-component',
interval=1*6000,
n_intervals=0
)
])
#app.callback(
Output('graph','figure'),
[Input('interval-component', 'n_intervals')]
)
def update_df(n):
updated_df = pd.read_csv('example.csv', encoding="WINDOWS-1252")
fig = px.scatter(updated_df, x='Date', y='Deviation', height=800)
fig.update_layout(
yaxis_tickformat = '.0%',
)
fig.update_xaxes(
rangeslider_visible=True,
rangeselector=dict(
)
)
return fig
if __name__ == '__main__':
app.run_server(debug=True)
I think your issue must have something to do with your file specifically, because the following code based exactly off as you provide (with the exception of generation of random matching-df timeseries data), works perfectly updating with an interval of every 6 seconds:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
np.random.seed(2019)
def get_random_deviation_ts_df(N=100):
rng = pd.date_range("2019-01-01", freq="D", periods=N)
df = pd.DataFrame(np.random.rand(N, 1), columns=["Deviation"], index=rng)
df["Date"] = df.index
return df
app = dash.Dash(__name__)
server = app.server
# df = pd.read_csv('example.csv', encoding="WINDOWS-1252")
app.layout = html.Div(
[
dcc.Graph(id="graph"),
dcc.Interval(
id="interval-component", interval=1 * 6000, n_intervals=0
),
]
)
#app.callback(
Output("graph", "figure"), [Input("interval-component", "n_intervals")]
)
def update_df(n):
updated_df = (
get_random_deviation_ts_df()
) # pd.read_csv('example.csv', encoding="WINDOWS-1252")
fig = px.scatter(updated_df, x="Date", y="Deviation", height=800)
fig.update_layout(yaxis_tickformat=".0%",)
fig.update_xaxes(rangeslider_visible=True, rangeselector=dict())
return fig
if __name__ == "__main__":
app.run_server(debug=True)

How to use a boolean switch to update a graph in Dash?

I'm new in Dash. I'm trying to use a daq.BooleanSwitch() like an input to callback a graph. I can display a message but I have troubles with the graph.
Does anyone have any advice that can help me?
import dash
from dash.dependencies import Input, Output
import dash_daq as daq
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1("Here we go"),
daq.BooleanSwitch(id='my_pb', on=False,color="red"),
html.Div(id='power-button-result-1'),
dcc.Graph(id="plot")
])
#app.callback(
Output('power-button-result-1', 'children'),
Input('my_pb', 'on')
)
def update_output(on):
x = '{}'.format(on)
if x == "True":
return "Hi Iḿ using DASH"
#app.callback(
Output('plot', 'figure'),
Input('my_pb', 'on')
)
def figura(on):
x = '{}'.format(on)
if x == "True":
# fig1 = Code to do a nice plot
return fig1
if __name__ == "__main__":
app.run_server(port = 1895)
My DASH output look like this:
I took a look at your code, and a couple changes were necessary:
import dash
import dash_daq as daq
from dash import dcc
from dash import html
from dash.dependencies import Input
from dash.dependencies import Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1("Here we go"),
daq.BooleanSwitch(id="my_pb", on=False, color="red"),
html.Div(id="power-button-result-1"),
]
)
#app.callback(
Output("power-button-result-1", "children"),
Input("my_pb", "on"),
)
def update_output(on):
x = "{}".format(on)
if x == "True":
return [dcc.Graph(id="plot")]
if __name__ == "__main__":
app.run_server(debug=True)
You were super close - I think you only need one callback. Here, you can see the boolean switch now toggles the display (or not) of the dcc.Graph object. Is this what you were looking for?
↓ (toggle the switch)
If you want the graph to already be displayed, and then updated upon toggling, here's a slightly modified expanded version of same code above to do that:
import dash
import dash_daq as daq
from dash import dcc
from dash import html
from dash import no_update
from dash.dependencies import Input
from dash.dependencies import Output
import plotly.express as px
import pandas as pd
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1("Here we go"),
daq.BooleanSwitch(id="my_pb", on=False, color="red"),
html.Div(
[dcc.Graph(id="plot")], id="power-button-result-1"
),
]
)
#app.callback(
Output("power-button-result-1", "children"),
Input("my_pb", "on"),
)
def update_output(on):
df = px.data.iris()
if on:
fig = px.scatter(df, x="sepal_width", y="sepal_length")
dcc.Graph(figure=fig)
return [dcc.Graph(figure=fig)]
else:
fig = px.scatter()
return [dcc.Graph(figure=fig)]
if __name__ == "__main__":
app.run_server(debug=True)
There - that's much better, hopefully helpful?

Plotly-Dash: How to code interactive callbacks for hover functions in plotly dash

Is it possible to have a text field at the bottom of a graph in dash that displays the text for the point they are on (showing hover data as plain text). So the text box will be able to make changes when users hover over a certain point. I have defined a dcc.Graph component and the app layout but am not sure how to define the callback function for the hoverdata.
I have used the below code to define dcc.Graph and app.layout
fig = go.Figure(data=plot_data, layout=plot_layout)
app.layout = html.Div([
dcc.Graph(figure=fig),
html.Div([
dcc.Markdown(id='mpg-metrics')
],style={'width':'20%','display':'inline-block'})
])
Any help with the callback will be great. thanks in advance
Yes, that's very possible! Since you haven't provided a complete description of your setup, I've put together a minimal example that draws on elements from dash.plotly.com/interactive-graphing and https://community.plotly.com/: Use Hover Trace As Input for Callback that among other things describes the use of hover data in callbacks. The code snippet below will produce the following app for JupyterDash. If you'd like to run a standard dash app, just rewrite it following these steps.
The solution I've put together should do exactly what you're aiming for. Every time you hover over a point on one of the lines in the figure in the dcc.Graph component, a set of details about the trace is displayed in the html.Pre component under it, such as x and y values. Try it out and let me know how it works out for you!
App 1:
If you'd like to retrieve only certain elements of the output, you can subset the output like this:
json.dumps({'Date:':hoverData['points'][0]['x'],
'Value:':hoverData['points'][0]['y']}, indent = 2)
App 2:
Complete code for JupyterDash, App1
import json
from textwrap import dedent as d
import pandas as pd
import plotly.graph_objects as go
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
# app info
app = JupyterDash(__name__)
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
# data and basic figure
x = np.arange(20)+10
fig = go.Figure(data=go.Scatter(x=x, y=x**2, mode = 'lines+markers'))
fig.add_traces(go.Scatter(x=x, y=x**2.2, mode = 'lines+markers'))
app.layout = html.Div([
dcc.Graph(
id='basic-interactions',
figure=fig,
),
html.Div(className='row', children=[
html.Div([
dcc.Markdown(d("""
Click on points in the graph.
""")),
html.Pre(id='hover-data', style=styles['pre']),
], className='three columns'),
])
])
#app.callback(
Output('hover-data', 'children'),
[Input('basic-interactions', 'hoverData')])
def display_hover_data(hoverData):
return json.dumps(hoverData, indent=2)
app.run_server(mode='external', port = 8070, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)
Complete code for JupyterDash, App2
import json
from textwrap import dedent as d
import pandas as pd
import plotly.graph_objects as go
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
# app info
app = JupyterDash(__name__)
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
# data and basic figure
y = np.arange(100)+10
x = pd.date_range(start='1/1/2021', periods=len(y))
fig = go.Figure(data=go.Scatter(x=x, y=y**2, mode = 'lines+markers'))
fig.add_traces(go.Scatter(x=x, y=y**2.2, mode = 'lines+markers'))
app.layout = html.Div([
dcc.Graph(
id='basic-interactions',
figure=fig,
),
html.Div(className='row', children=[
html.Div([
dcc.Markdown(d("""
Click on points in the graph.
""")),
html.Pre(id='hover-data', style=styles['pre']),
], className='three columns'),
])
])
#app.callback(
Output('hover-data', 'children'),
[Input('basic-interactions', 'hoverData')])
def display_hover_data(hoverData):
try:
return json.dumps({'Date:':hoverData['points'][0]['x'],
'Value:':hoverData['points'][0]['y']}, indent = 2)
except:
return None
app.run_server(mode='external', port = 8070, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)

Plotly in Dash Python is not getting updated

When I run the code i get the graph but the graph is not getting updated i am calling the data from my sql laptop sql management studio.
Kindly let me know what needs to be done the X axis contains date and time and Y axis contains data in numeric form which is getting updated automatically
Code:
import pandas as pd
import pyodbc
import numpy as np
server ='LAPTOP-OO3V36UA\SQLEXPRESS'
db='addy'
conn=pyodbc.connect('DRIVER={SQL Server}; SERVER=' +server + ';DATABASE=' + db +
';Trusted_connection=yes')
sql="""
SELECT * FROM Summry
"""
df=pd.read_sql(sql ,conn)
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
from random import random
import plotly
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='live-update-graph-scatter', animate=True),
dcc.Interval(
id='interval-component',
interval=1*1000
)
])
#app.callback(Output('live-update-graph-scatter', 'figure'),
[Input('interval-component', 'interval')])
def update_graph_scatter():
df=pd.read_sql(sql ,conn)
trace1=go.Scatter(
y=df['ACL'],
x = df['DateandnTime'],
mode='lines',
name='ACL'
)
layout = go.Layout(
title='Daily Monitoring'
)
return {'data': trace1, 'layout': layout}
if __name__ == '__main__':
app.run_server()
You've set your callback's input to
Input('interval-component', 'interval')
But you want
Input('interval-component', 'n_intervals')
The interval property sets how frequently n_intervals gets updated. The change in n_intervals is what can be used to trigger the callback.
Here's the documentation: https://dash.plotly.com/dash-core-components/interval

Categories

Resources