Hi Dash world,
I am working on an app that allows the user to select a customer, click a button to download a bunch of data from our internal DB, and then produce some graphs on the data. I believe I have the workflow correct and the app works as expected however I get a bunch of errors/warnings in the background.
Two questions here:
- Is there a way to stop callbacks given input conditions to mitigate these errors?
- Is having ~15 hidden JSON data frames actually the most efficient way to share data between callbacks?
Here’s a pseudo code example of my app:
app.layout = html.Div([
dcc.Dropdown(id='custDropDown', Select Customer, ...)
html.button(id='dl-button', ...)
dcc.Graph(id='graph-1',...)
.....
html.Div(id='dataset-1', style={'display': 'none'})
])
#download the data
@app.callback(
Output('dataset-1', 'children'),
[Input('dl-button', 'n_clicks')],
[State('custDropDown', 'value')])
def dl_the_date(n_clicks, cust):
DF = download the data to data frame
return DF.to_json(date_format='iso', orient='split')
#make the graph
@app.callback(
Output('graph-1', 'figure'),
[Input('dataset-1', 'children')],
[State('custDropDown', 'value')])
def make_the_graph(data, cust):
df = pd.read_json(data, orient='split)
make the graph
return (plotly graph....)
I have many modules set up like this and I get the error below on the read_json
line before the data is downloaded:
raise ValueError(msg.format(_type=type(filepath_or_buffer)))
Any help is much appreciated.
1 Like
I think an easier more efficient way is to load the DataFrame once, and in the callback functions you can do the filtering you need to return a subset of the df and / or to return a plot based on the dropdown.
Here is my suggested modification to your code with some comments:
app = dash.Dash()
data_df = pd.read_csv('my_df.csv') # or read_sql, read_json etc.
app.layout = html.Div([
dcc.Dropdown('custDropDown'),
# no need for a button here, but you can add one if it makes sense based on the business logic
dcc.Graph('graph-1'),
# no need for the hidden div here, since you alway have the data in `data_df`
])
# no need for the first callback function, having loaded the data, the DataFrame will be available as a
# variable in memory, and you can filter / slice / dice in the next function based on needs
@app.callback(Output('graph-1', 'figure'),
[Input('custDropDown', 'value')])
# since you have a variable with the dataframe, there is no need to load every time
def make_the_graph(value):
df = data_df[some_filter_based_on_value] # you are simply filtering an available DataFrame
return {'data': [go.Scatter(x=df[var1], y=df[var2])]} # or whatever type of graph you want to produce
My suggested approach is NOT a good idea if your data is constantly changing (users need live data that gets updated daily for example). In this case you might need to move the read_csv call inside the callback function, so it loads a fresh copy of the data every time, or some other solution.
Hope this makes sense!
Not sure what these errors are…
No:) I think as mentioned above, with this approach you wouldn’t need to have hidden divs.
Good luck!