-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add reactive expressions / blocks #49
Comments
October 12th, 2017 Edit: This topic is now it's own part of the user guide. Please see http://plot.ly/dash/sharing-data-between-callbacks Ah, that's interesting. Thanks for sharing! I'm not sure if these arguments apply to Dash, but I'm curious to learn more. Some notes:
global_df = pd.read_csv('...')
app.layout = html.Div([
dcc.Graph(id='graph'),
html.Table(id='table'),
dcc.Dropdown(id='dropdown')
])
def clean_data(df, value):
# some expensive clean data step
[...]
return cleaned_df
@app.callback(Output('graph', 'figure'), [Input('dropdown', 'value'])
def update_graph(value):
dff = clean_data(global_df, value)
figure = create_figure(dff)
return figure
@app.callback(Output('table', 'figure'), [Input('dropdown', 'value'])
def update_table(value):
dff = clean_data(global_df, value)
table = create_table(dff)
return table
Here's how you would do this in a hidden div: global_df = pd.read_csv('...')
app.layout = html.Div([
dcc.Graph(id='graph'),
html.Table(id='table'),
dcc.Dropdown(id='dropdown'),
html.Div(id='intermediate-value', style={'display': 'none'})
])
@app.callback(Output('intermediate-value', 'children'), [Input('dropdown', 'value')])
def clean_data(value):
# some expensive clean data step
cleaned_df = your_expensive_clean_or_compute_step(value)
return cleaned_df.to_json() # or, more generally, json.dumps(cleaned_df)
@app.callback(Output('graph', 'figure'), [Input('intermediate-value', 'children'])
def update_graph(jsonified_cleaned_data):
dff = pd.read_json(jsonified_cleaned_data) # or, more generally json.loads(jsonified_cleaned_data)
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) # or, more generally json.loads(jsonified_cleaned_data)
table = create_table(dff)
return table Finally, note that when you run just |
Thanks the On the performance side, the additional benefit of having a 'ReactiveExpressions' is the caching could be invisibly globally handled by Dash rather than having it on a function-by-function basis (what Shiny does). I'll need to study the code a bit better to see if there is anything else that might work. |
For future readers, I have written up some solutions to this problem in a new section of the user guide: http://plot.ly/dash/sharing-data-between-callbacks |
@chriddyp and @kmader, the hidden Div appears to be a bad idea in practice. I just spent the better (or worse) part of 2 days trying to figure out why my app was working flawlessly when run on my desktop but stumbled when pushed to the server (RHEL 7.1). As it turns out, the issue had to do with my use of a hidden Div to pass data between callbacks. When the DataFrame reached a certain number of rows (861), it would fail to execute the callbacks that depended on those Divs. I am guessing this has something to do with a size limit on Divs in HTML, but I am not certain. I will try to post a reproducible example here in the next couple of days. So far, Dash has been fantastic! But this has been a massive frustration. Live and learn... |
Please try to recreate a reproducible example. I have used this method with 5MB of data successfully before, I'm not aware of any inherent limitations. Another issue could be a request or response size limitation on the server that you are deploying it on (frequently the default is like 1MB). |
I'll try to recreate an example. It is probably the request/response size limitation as you indicate. I'm a newb web-dev, hence why Dash has been fantastic for me! I'm also checking with my server admin to see if they're imposing some kind of size limit. Thanks for the speedy response. |
Closing this. We have to do things differently than other frameworks because we support multiple-processes. We have documented several ways to pass intermediate data around in https://dash.plot.ly/sharing-state-between-callbacks and this will only get better with declarative client-side transformations (#266 ) and support for multiple outputs (#80 ) |
As someone who works a lot in Shiny, and am trying out dash, really expected this equivalency in dash in some form or the other. This is kind of a game changer for me.
What if the function (e.g. |
…r the figures. Tactic to transfer long Monte Carlo run between callbacks is following plotly/dash#49 (comment) Which is using Hidden div inside the app that stores the intermediate value (using JSON)
One of the best features in shiny is the ability to make reactive expression tying together a number of different tasks so that multiple outputs could depend on the same intermediate step. This is particularly useful for example below when having a table and a plot depend on the same input which is being filtered/transformed using some of the reactive components. It also allows many of the longer expressions to be rewritten more modularly with fewer inputs
Clearly in dash this is a bit trickier, but presumably something like a new type of Dependency
The text was updated successfully, but these errors were encountered: