I am creating a figure with go.Figure. After I create the figure, I can look at the x and y data in the first trace with figure[‘data’][0][‘x’‘] and figure[‘data’][0][‘y’]. x and y are numpy.ndarrays. When I get the figure back in the Status of a callback, x and y are changed to a dict with keys dict_keys([‘dtype’, ‘bdata’, ‘_inputArray’]). It looks like I could get to the data for x and y by figure[‘data’][0][‘x’][’_inputArray’].values() and figure[‘data’][0][y’][‘_inputArray’].values() Is there a better or “proper” way to retrieve the x and y data for a trace in a figure?
@Brent thanks for the question.
Can you please share the code you wrote for this figure and the minimal Dash app examples?
#!/usr/bin/env python3
"""Minimal dash program."""
from dash import callback, Dash, dcc, Input, Output, State
import dash_bootstrap_components as dbc
import pandas as pd
import plotly.express as px
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)
dataframe = pd.DataFrame({'x': [1, 3, 5], 'y': [2, 4, 6]})
figure = px.line(dataframe, x='x', y='y')
print(f"x after creating figure: {figure['data'][0]['x']}")
app.layout = dbc.Container([dcc.Graph(id='graph', figure=figure),
dcc.RangeSlider(1, 5, value=[1, 5], id='range-slider')])
@callback(Output('graph', 'figure'),
Input('range-slider', 'value'),
State('graph', 'figure'))
def fill_graph(fig_range, fig):
print(f"x in callback: {fig['data'][0]['x']}")
print(f"x values in callback: {list(fig['data'][0]['x']['_inputArray'].values())[:-3]}")
fig['layout']['xaxis']['range'] = fig_range
return fig
if __name__ == '__main__':
app.run_server(debug=True)
@Brent, are you trying to return a new figure with the updated ranges?
If so, I think you can use Patch:
from dash import callback, Dash, dcc, Input, Output, Patch
import dash_bootstrap_components as dbc
import pandas as pd
import plotly.express as px
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
dataframe = pd.DataFrame({'x': [1, 3, 5], 'y': [2, 4, 6]})
figure = px.line(dataframe, x='x', y='y')
app.layout = dbc.Container([
dcc.Graph(id='graph', figure=figure),
dcc.RangeSlider(1, 5, value=[1, 5], id='range-slider')
])
@callback(
Output('graph', 'figure'),
Input('range-slider', 'value')
)
def fill_graph(fig_range):
# Modify the layout range
patched_fig = Patch()
patched_fig['layout']['xaxis']['range'] = fig_range
return patched_fig
if __name__ == '__main__':
app.run(debug=True)
Or are you trying to retrieve all the x and y data of the figure after using the rangeSlider?
@adamschroeder, my actual use case is more complex of course. Patch does look very useful. However, in this case I am doing more than updating the figure. The data in the graph is a histogram. I actually have 2 range sliders. One for the x values and another one for the percentile of the x values. The sliders work in tandem. If the user moves/changes the x value slider, I also have to show the corresponding movement on the percentile slider and vice versa. In order to compute the percentile slider value, I need the x and y values for the graph. I am trying to prevent having to rebuild the histogram every time the range sliders are moved. I could use a Store to store the x and y values but they can be large.