plotly dash:创建多个回调(带循环?)
plotly dash: create multiple callbacks (with loop?)
假设我有一个包含 20 个参数的模型,我为每个参数制作了一个输入组件。
[dcc.Input(type = 'number', id = 'input %i'%i) for i in range(20)]
我想要一个按钮 html.Button('populate parameters', id = 'button populate')
,它应该为所有输入填充最佳预拟合值。
代码应该如下所示,但它不起作用。
for i in range(20):
@app.callback(
dash.dependencies.Output('input %i'%i, 'value'),
[dash.dependencies.Input('button populate', 'n_clicks')]
)
def update(ignore):
return np.random.uniform()
我是否必须为具有相同功能的每个输出编写 20 个回调?我找不到一次性制作它们的方法(循环?)
您可以根据需要在回调中输入任意多个 parameters/argument。
但是只有一个输出.
为我解决类似案例的是:
@app.callback(
[Output('output-id', 'children')],
[Input('button-trigger', 'n_clicks'],
[State('input-one', 'value'),
...
[State('input-twenty', 'value')]
)
def my_fancy_function(n_clicks, v1, ..., v20):
return sth_awesome
State()
与 Input()
相反,当输入值更改时不会触发回调。
n_clicks
每次点击都会更改 +1,但不需要使用。
如果您的参数相互依赖,您将需要更多回调。
但是...有 20 个参数 There must be a better way
我遇到过同样的问题并找到了解决方案。你所做的是绕过装饰器并直接调用 app.callback
函数:
def update(ignore):
return np.random.uniform()
for i in range(20):
app.callback(
dash.dependencies.Output('input %i' % i, 'value'),
[dash.dependencies.Input('button populate', 'n_clicks')]
)(update)
我做了类似的事情来在页面重新加载后填充我的布局组件。
感谢第一个回调,组件的状态存储在 dcc.Store 组件中。
第二个回调是在布局组件的状态更改或访问选项卡时填充布局组件(布局在 dcc.Tabs)
dash_layout_components = {
'time_slider_app2': 'value',
'backtest_choice_app2': 'values',
'asset_selection_app2': 'value',
'graph_selection_app2': 'values'
}
stored_layout_value_name = [key[:key.rfind('a')] + value for key, value in
dash_layout_components.items()]
set_back_and_display_graph_input = {
'store_layout_data': 'modified_timestamp',
'tabs': 'value'
}
@app.callback(
Output('store_layout_data', 'data'),
[Input(key, value) for key, value in dash_layout_components.items()])
def store_layout(time_slider_value, backtest_choice_values, assets_selection_values, graph_selection_values):
data_json = {
'time_slider_value': time_slider_value,
'backtest_choice_values': backtest_choice_values,
'asset_selection_value': assets_selection_values,
'graph_selection_values': graph_selection_values
}
return data_json
for component_id, component_property in dash_layout_components.items():
@app.callback(
Output(component_id, component_property),
[Input(key, value) for key, value in set_back_and_display_graph_input.items()],
[State('store_layout_data', 'data'),
State(component_id, 'id')]
)
def set_back_component(bouton_ts, tabs_value, layout_state_data, component): # dynamiser l'arrivée des paramètres. piste, en créer une liste entre le for et le callback
if tabs_value != '/app2':
raise PreventUpdate
if layout_state_data is None:
return []
else:
store_layout_component_name = stored_layout_value_name[list(dash_layout_components.keys()).index(component)]
return layout_state_data[store_layout_component_name]
请注意,您无法访问函数 (set_back_component(...))
内的迭代值(component_id 和 component_property)
在dash >= 1.11.0 you may use Pattern-Matching Callbacks。定义回调时不需要循环。
例子
1。导入回调选择器
- 导入
dash.dependecies.ALL
:
from dash.dependencies import Input, Output, State, ALL
- 其他可用的回调选择器是
MATCH
和 ALLSMALLER
。
2。使用字典作为 id
- 使用
id
定义您的组件,它是一个 字典 。您可以选择任何键,但例如 type
和 id
是非常合理的选择。所以,而不是
[dcc.Input(type = 'number', id = 'input %i'%i) for i in range(20)]
使用
[
dcc.Input(type='number',
id={
'type': 'my-input-type',
'id': 'input %i' % i
}) for i in range(20)
]
3。使用带有 @app.callback
的回调选择器
- 定义回调时使用
ALL
回调选择器:
@app.callback(
dash.dependencies.Output({
'type': 'my-input-type',
'id': ALL
}, 'value'), [dash.dependencies.Input('button populate', 'n_clicks')])
def update(ignore):
return np.random.uniform()
假设我有一个包含 20 个参数的模型,我为每个参数制作了一个输入组件。
[dcc.Input(type = 'number', id = 'input %i'%i) for i in range(20)]
我想要一个按钮 html.Button('populate parameters', id = 'button populate')
,它应该为所有输入填充最佳预拟合值。
代码应该如下所示,但它不起作用。
for i in range(20):
@app.callback(
dash.dependencies.Output('input %i'%i, 'value'),
[dash.dependencies.Input('button populate', 'n_clicks')]
)
def update(ignore):
return np.random.uniform()
我是否必须为具有相同功能的每个输出编写 20 个回调?我找不到一次性制作它们的方法(循环?)
您可以根据需要在回调中输入任意多个 parameters/argument。 但是只有一个输出.
为我解决类似案例的是:
@app.callback(
[Output('output-id', 'children')],
[Input('button-trigger', 'n_clicks'],
[State('input-one', 'value'),
...
[State('input-twenty', 'value')]
)
def my_fancy_function(n_clicks, v1, ..., v20):
return sth_awesome
State()
与 Input()
相反,当输入值更改时不会触发回调。
n_clicks
每次点击都会更改 +1,但不需要使用。
如果您的参数相互依赖,您将需要更多回调。
但是...有 20 个参数 There must be a better way
我遇到过同样的问题并找到了解决方案。你所做的是绕过装饰器并直接调用 app.callback
函数:
def update(ignore):
return np.random.uniform()
for i in range(20):
app.callback(
dash.dependencies.Output('input %i' % i, 'value'),
[dash.dependencies.Input('button populate', 'n_clicks')]
)(update)
我做了类似的事情来在页面重新加载后填充我的布局组件。
感谢第一个回调,组件的状态存储在 dcc.Store 组件中。 第二个回调是在布局组件的状态更改或访问选项卡时填充布局组件(布局在 dcc.Tabs)
dash_layout_components = {
'time_slider_app2': 'value',
'backtest_choice_app2': 'values',
'asset_selection_app2': 'value',
'graph_selection_app2': 'values'
}
stored_layout_value_name = [key[:key.rfind('a')] + value for key, value in
dash_layout_components.items()]
set_back_and_display_graph_input = {
'store_layout_data': 'modified_timestamp',
'tabs': 'value'
}
@app.callback(
Output('store_layout_data', 'data'),
[Input(key, value) for key, value in dash_layout_components.items()])
def store_layout(time_slider_value, backtest_choice_values, assets_selection_values, graph_selection_values):
data_json = {
'time_slider_value': time_slider_value,
'backtest_choice_values': backtest_choice_values,
'asset_selection_value': assets_selection_values,
'graph_selection_values': graph_selection_values
}
return data_json
for component_id, component_property in dash_layout_components.items():
@app.callback(
Output(component_id, component_property),
[Input(key, value) for key, value in set_back_and_display_graph_input.items()],
[State('store_layout_data', 'data'),
State(component_id, 'id')]
)
def set_back_component(bouton_ts, tabs_value, layout_state_data, component): # dynamiser l'arrivée des paramètres. piste, en créer une liste entre le for et le callback
if tabs_value != '/app2':
raise PreventUpdate
if layout_state_data is None:
return []
else:
store_layout_component_name = stored_layout_value_name[list(dash_layout_components.keys()).index(component)]
return layout_state_data[store_layout_component_name]
请注意,您无法访问函数 (set_back_component(...))
内的迭代值(component_id 和 component_property)在dash >= 1.11.0 you may use Pattern-Matching Callbacks。定义回调时不需要循环。
例子
1。导入回调选择器
- 导入
dash.dependecies.ALL
:
from dash.dependencies import Input, Output, State, ALL
- 其他可用的回调选择器是
MATCH
和ALLSMALLER
。
2。使用字典作为 id
- 使用
id
定义您的组件,它是一个 字典 。您可以选择任何键,但例如type
和id
是非常合理的选择。所以,而不是
[dcc.Input(type = 'number', id = 'input %i'%i) for i in range(20)]
使用
[
dcc.Input(type='number',
id={
'type': 'my-input-type',
'id': 'input %i' % i
}) for i in range(20)
]
3。使用带有 @app.callback
的回调选择器
- 定义回调时使用
ALL
回调选择器:
@app.callback(
dash.dependencies.Output({
'type': 'my-input-type',
'id': ALL
}, 'value'), [dash.dependencies.Input('button populate', 'n_clicks')])
def update(ignore):
return np.random.uniform()