How to get the count from a dataframe from a Dash Callback - python

I'd like to display the count of certain criteria inside a div in my dash layout based off callback selection from dropdown.
I'm able to get the dropdown for the values in a pandas dataframe column, but I'm having trouble figuring out how to display the total count of the a selected element of the column.
For example, I've written a function in Jupyter notebook to get a count
def getCount(df, selected_org):
totCount = df[df['ORGANIZATIONS'] == selected_org].AGENCY.count()
return count
selected_org = 'REGION 1'
getCount(df, selected_org)
Which displays a value of: 3187
This value is the result of my selected_org variable.
Now, I'd like to do the same thing in my dash layout based off the selection from dropdown. I used much of the code here to get started from Udemy course: Interactive Python Dashboards with Plotly and Dash
I start with my layout:
org_options = []
for org in df['ORG_CODE_LEVEL_2_SHORT'].unique():
org_options.append({'label': str(org), 'value': org})
app.layout = html.Div(children=[
html.Label('Select Org:'),
dcc.Dropdown(id='org-dropdown', options=org_options,
value=df['ORG_CODE_LEVEL_2_SHORT'].min()),
html.P(html.Div(id='container'))
Then my call back:
#app.callback(
Output(component_id='container', component_property='children'),
[Input(component_id='org-dropdown', component_property='value')])
def update_table(selected_org):
filtered_org = df[df['ORG_CODE_LEVEL_2_SHORT'] == selected_org]
return getCount(df, filtered_org)
And a function to generate the count:
def getCount(df, selected_org):
totCount = df[df['ORG_CODE_LEVEL_2_SHORT'] ==
selected_org].AGENCY_INFO_5.count()
return html.H2(totCount)
Which give me the following:
But it isn't giving me the count. Any help is appreciated.
Final complete program:
import os
import glob
import pandas as pd
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
# DATA FROM EEPROFILE
path = r'mydata'
extension = 'xlsx'
os.chdir(path)
files = [i for i in glob.glob('*.{}'.format(extension))]
latest_file = max(files, key=os.path.getctime)
df = pd.DataFrame()
eeprofi = pd.read_excel(latest_file, converters={'ORG_CODE_LEVEL_3': str})
df = df.append(eeprofi)
def getCount(df, selected_org):
totCount = df[df['ORG_CODE_LEVEL_2_SHORT'] == selected_org].AGENCY_INFO_5.count()
return html.H2(totCount)
org_options = []
for org in df['ORG_CODE_LEVEL_2_SHORT'].unique():
org_options.append({'label': str(org), 'value': org})
app.layout = html.Div(children=[
html.Label('Select Org:'),
dcc.Dropdown(id='org-dropdown', options=org_options, value=df['ORG_CODE_LEVEL_2_SHORT'].min()),
html.P(html.Div(id='container'))
])
#app.callback(
Output(component_id='container', component_property='children'), [Input(component_id='org-dropdown', component_property='value')])
def update_table(selected_org):
filtered_org = df[df['ORG_CODE_LEVEL_2_SHORT'] == selected_org]
return getCount(df, filtered_org)
if __name__ == '__main__':
app.run_server()

Your input is a children so you should return a list and not html.H2(your_count) like you did ;) so the solution is to replace this function
def getCount(df, selected_org):
totCount = df[df['ORG_CODE_LEVEL_2_SHORT'] == selected_org].AGENCY_INFO_5.count()
return html.H2(totCount)
by this one :
def getCount(df, selected_org):
totCount = df[df['ORG_CODE_LEVEL_2_SHORT'] == selected_org].AGENCY_INFO_5.count()
return [html.H2(totCount)]

Related

Dash, merge two dashboards and add a button

I'm pretty new to Dash. I created two dashboards that read from two different dataframes. They work well individually. I would like to merge them in a single one, giving the possibility to the user to access them using a dropdown menu.
I would like to also add a button which (when clicked) returns a function.
Those are the two dashboards:
first one:
import pandas as pd
df1 = pd.read_csv('/df1.csv')
# Import libraries
from dash import Dash, html, dcc, Input, Output
import pandas as pd
import plotly.express as px
# Create the Dash app
app = Dash()
# Set up the app layout
options_dropdown = dcc.Dropdown(options=df1['options'].unique(),
value='wordcount')
app.layout = html.Div(children=[
html.H1(children='offensive/non offensive username activity dashboard'),
options_dropdown,
dcc.Graph(id='df1')
])
# Set up the callback function
#app.callback(
Output(component_id='df1', component_property='figure'),
Input(component_id=options_dropdown, component_property='value')
)
def update_graph(sel_option):
filtered_options = df1[df1['options'] == sel_option]
bar_fig = px.bar(filtered_options,
x= "user", y = "value",
color='user',
color_discrete_map={
'off': '#d62728',
'non_off': 'green'},
title=f' average {sel_option}',
width=500, height=500)
return bar_fig
print(df1)
# Run local server
if __name__ == '__main__':
app.run_server(debug=True)
second one:
import pandas as pd
df2 = pd.read_csv('/df2.csv')
# Import libraries
from dash import Dash, html, dcc, Input, Output
import pandas as pd
import plotly.express as px
# Create the Dash app
app = Dash()
# Set up the app layout
options_dropdown = dcc.Dropdown(options=df2['options'].unique(),
value='wordcount')
app.layout = html.Div(children=[
html.H1(children='offensive/non offensive username activity dashboard'),
options_dropdown,
dcc.Graph(id='df2')
])
# Set up the callback function
#app.callback(
Output(component_id='df2', component_property='figure'),
Input(component_id=options_dropdown, component_property='value')
)
def update_graph(sel_option):
filtered_options = df2[df2['options'] == sel_option]
line_fig = px.line(filtered_options,
x= "Week_Number", y = "value",
color='offensive',
color_discrete_map={
1: '#d62728',
0: 'green'},
title=f' average {sel_option}')
return line_fig
print(df2)
# Run local server
if __name__ == '__main__':
app.run_server(debug=True)
and this is the function I want to implement pressing a button:
sentences = []
df3 = pd.read_csv('/df3.csv')
def cool_function():
ext = rd.randint(0,len(df3.offensive))
return rd.choice(sentences).format(df3.author[ext], "", df3.text[ext])
How do I merge those three elements in a single dashboard?

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?

python plolty dash - read .pkl files and display them in plotly dash

i changed the following code from using ".png" to ".pkl". but this doesn't work
import plotly.express as px
import joblib
#generate example pkl
fig = px.scatter(x=range(10), y=range(10))
joblib.dump(fig, "img_dash/figure.pkl")
#%%
import dash
import dash_core_components as dcc
import dash_html_components as html
import flask
import glob
import os
image_directory = 'img_dash/'
list_of_images = [os.path.basename(x) for x in glob.glob('{}*.pkl'.format(image_directory))]
static_image_route = '/static/'
app = dash.Dash()
app.layout = html.Div([
dcc.Dropdown(
id='image-dropdown',
options=[{'label': i, 'value': i} for i in list_of_images],
value=list_of_images[0]
),
html.Img(id='image')
])
#app.callback(
dash.dependencies.Output('image', 'src'),
[dash.dependencies.Input('image-dropdown', 'value')])
def update_image_src(value):
return static_image_route + value
#app.server.route('{}<image_path>.pkl'.format(static_image_route))
def serve_image(image_path):
image_name = '{}.pkl'.format(image_path)
if image_name not in list_of_images:
raise Exception('"{}" is excluded from the allowed static files'.format(image_path))
return flask.send_from_directory(image_directory, image_name)
if __name__ == '__main__':
app.run_server(debug=False)
i expect to show the .pkl files in the dashboard with hover-function. may other formats also possible! i was not able to check this.
I recommend you to use a Graph component here instead of an Img component since you want to display these figures dynamically.
Since each pkl file already stores a Figure you can just dynamically load these files using joblib in your callback based on the dropdown value.
Example based on your code:
# Example figures for demo purposes
fig1 = px.scatter(x=range(10), y=range(10))
fig2 = px.scatter(x=range(15), y=range(15))
fig3 = px.scatter(x=range(20), y=range(20))
joblib.dump(fig1, "img_dash/figure1.pkl")
joblib.dump(fig2, "img_dash/figure2.pkl")
joblib.dump(fig3, "img_dash/figure3.pkl")
# ...
image_directory = "img_dash/"
list_of_images = [
os.path.basename(x) for x in glob.glob("{}*.pkl".format(image_directory))
]
app = dash.Dash()
app.layout = html.Div(
[
dcc.Dropdown(
id="image-dropdown",
options=[{"label": i, "value": i} for i in list_of_images],
value=list_of_images[0],
),
dcc.Graph(id="graph"),
]
)
#app.callback(
dash.dependencies.Output("graph", "figure"),
[dash.dependencies.Input("image-dropdown", "value")],
)
def update_graph(file):
return joblib.load(os.path.join(image_directory, file))
if __name__ == "__main__":
app.run_server(debug=False)

Dash Python interval error with live update

I’m learning python and dash and I’m building an application for monitoring my trading.
I’ve adapted the code from : “Live Updating Components” example (Orbital Satellite). It works well on jupyter notebook and repl.it but I have an error when I try it on my computer :
"Traceback (most recent call last):
File "orbital.py", line 62, in
Input('interval-component', 'n_intervals'))"
“The input argument interval-component.n_intervals must be a list or tuple of
dash.dependencies.Inputs.”
I don’t understand why
Here is my code :
import ccxt
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly
from dash.dependencies import Input, Output
import pandas as pd
app = dash.Dash(__name__)
ftx = ccxt.ftx({'verbose': True})
ftx = ccxt.ftx({
'apiKey': '',
'secret': '',
})
app.layout = html.Div(
html.Div([
html.H4('FTX Live Feed'),
html.Div(id='live-update-text'),
dcc.Interval(
id='interval-component',
interval=1*1000, # in milliseconds
n_intervals=0
)
])
)
class Client:
"""A sample client class"""
def __init__(self):
self.pnl = []
#classmethod
def get_balances(client):
try:
balance = ftx.fetch_balance()
except ccxt.BaseError as e:
print(f"Could not get account with error: {e}")
raise e
else:
result = balance["info"]["result"]
total = []
for x in result:
if float(x["free"]) > 0.0:
total.append(x["usdValue"])
a = list(map(float, total))
df = pd.Series(a)
# global totCap
totCap = df.sum()
return totCap
#app.callback(Output('live-update-text', 'children'),
Input('interval-component', 'n_intervals'))
def update_metrics(n):
arc = Client().get_balances()
style = {'padding': '5px', 'fontSize': '16px'}
return [
html.Span('Balance: {0:.2f}'.format(arc), style=style)
]
if __name__ == '__main__':
app.run_server(host="0.0.0.0", port="8050")
Here is a screenshot from the replit app :
replit dash
As the error is trying to say, you need to wrap your Input in a list, like this:
#app.callback(Output('live-update-text', 'children'),
[Input('interval-component', 'n_intervals')])

Unable to access dataframe while uploading form plotly-dash app

I am new to python and plotly-dash.
I am trying to use "Hidden Div" to store a data frame as suggested in dash tutorial 5.
But I am not able to process the uploaded file.
import base64
import io
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import pandas as pd
#global_df = pd.read_csv('...')
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='graph'),
html.Table(id='table'),
dcc.Upload(
id='datatable-upload',
children=html.Div(['Drag and Drop or ',html.A('Select Files')]),
),
# Hidden div inside the app that stores the intermediate value
html.Div(id='intermediate-value', style={'display': 'none'})
])
def parse_contents(contents, filename):
content_type, content_string = contents.split(',') #line 28
decoded = base64.b64decode(content_string)
if 'csv' in filename:
# Assume that the user uploaded a CSV file
return pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
return pd.read_excel(io.BytesIO(decoded))
elif 'xlsx' in filename:
# Assume that the user uploaded an excel file
return pd.read_excel(io.BytesIO(decoded))
#app.callback(Output('intermediate-value', 'children'),
[Input('datatable-upload', 'contents')],
[State('datatable-upload', 'filename')])
def update_output(contents, filename):
# some expensive clean data step
cleaned_df = parse_contents(contents, filename)
# more generally, this line would be
# json.dumps(cleaned_df)
return cleaned_df.to_json(date_format='iso', orient='split')
#app.callback(Output('graph', 'figure'), [Input('intermediate-value', 'children')])
def update_graph(jsonified_cleaned_data):
# more generally, this line would be
# json.loads(jsonified_cleaned_data)
dff = pd.read_json(jsonified_cleaned_data, orient='split')
figure = create_figure(dff)
return figure
#app.callback(Output('table', 'children'), [Input('intermediate-value', 'children')])
def update_table(jsonified_cleaned_data):
dff = pd.read_json(jsonified_cleaned_data, orient='split')
table = create_table(dff)
return table
if __name__ == '__main__':
app.run_server(port=8050, host='0.0.0.0')
I am getting the following error while running the code:
File "ipython-input-12-4bd6fe1b7399", line 28, in parse_contents
content_type, content_string = contents.split(',')
AttributeError: 'NoneType' object has no attribute 'split'
The callback is likely running on initialization with empty values. You can prevent this by adding something like this at the top of your callback:
if contents is None:
raise dash.exceptions.PreventUpdate

Categories

Resources