更新 Dash 中多个绘图的绘图

Posted

技术标签:

【中文标题】更新 Dash 中多个绘图的绘图【英文标题】:Update plots for multiple plots in Dash 【发布时间】:2021-05-31 19:46:45 【问题描述】:

我有一个非常基本的问题,主要是为了了解 Dash 在变量更改时如何处理图形更新过程。我刚刚开始构建仪表板,但我仍然不熟悉完整的语法。

我的布局中有一个绘图、一个下拉框、回调和更新函数,如下所示:

@app.callback(
    Output(component_id='plot1', component_property='figure'),
    Input(component_id='drop1', component_property='value')
)
def update_graph(sel):
    """ Stuff for updating the plot """
    return fig

哪个完美,但我不完全理解“为什么”。

现在,我的问题是……

    回调如何知道 update_graph() 是为了更新该图而调用的函数?它永远不会在回调方法中被调用,下拉选择的值永远不会真正传递到任何地方,等等。 如果我有多个动态图会怎样?我的布局中的另一个下拉框或任何其他反应元素,我想根据第二个输入对象更新第二个图表。我必须进行另一个回调和另一个更新功能?同样,每个回调如何知道要使用哪一个更新函数?

提前致谢!

【问题讨论】:

我会留给其他人为你写一个简短、简洁、正确的解释。与此同时,阅读有关decorators 和callbacks 的内容应该可以对整个事情有所了解。 【参考方案1】:

好的,我将仅用一张图表来解释 plotly 文档中的一个简单示例。一旦我们理解了一个图,那么多个图就会变得更容易理解。

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    html.H6("Change the value in the text box to see callbacks in action!"),
    html.Div(["Input: ",
              dcc.Input(id='my-input', value='initial value', type='text')]),
    html.Br(),
    html.Div(id='my-output'),

])


@app.callback(
    Output(component_id='my-output', component_property='children'),
    Input(component_id='my-input', component_property='value')
)
def update_output_div(input_value):
    return 'Output: '.format(input_value)


if __name__ == '__main__':
    app.run_server(debug=True)

所以开始让我们注意输入和输出component_id。请注意,输入的 component_iddcc.Input id 匹配。匹配的 id 表示装饰器 @app.callback 和布局对象之间存在链接。这个链接意味着一旦输入发生变化,装饰器将被调用,装饰器将查看其各自的输出 id。然后装饰器将寻求更新作为 HTML div 的输出组件。为了做到这一点,装饰器将始终查看其正下方的函数,在本例中为update_output_div。更改的值(输入)将传递给此函数。

好的,现在进入多个图表。在下面的代码中,我将省略 app.layout 声明,只是假设下面的每个 id(square、cube twos、threes、x^x、num-multi、dropdown)都链接到它们的对应项。

@app.callback(
    Output('square', 'children'),
    Output('cube', 'children'),
    Output('twos', 'children'),
    Output('threes', 'children'),
    Output('x^x', 'children'),
    Input('num-multi', 'value'),
    Input('dropdown', 'value2'))

def callback_a(v, v2):
   # update 

再一次,装饰器只会查找任何输入的变化,然后通过 callback_a 函数更新每个输出

所以回答你的第一个问题。回调将始终直接在其自身下方调用该函数,而无需您对其进行隐式编码。您当然可以决定在该函数内部调用更多函数。例如,如果我有多个可能不相关的输入,我可以查找实际触发的内容。

@app.callback(
    Output('map', 'figure'),
    Input('map','clickData'),
    Input('map','selectedData'))
def update_scatter_plots(
    ctx = dash.callback_context
    if ctx.triggered[0]['prop_id'] == 'map.clickData':
       #it was a click 
    elif ctx.triggered[0]['prop_id'] == 'map.selectedData':
       #it was a selection

这里我有一个地图,我有两个不同的输入,一个点击事件和一个选择事件,根据上下文,我可以决定如何处理传递的信息。

至于您的第二个问题,如果您希望我详细说明,请告诉我。

【讨论】:

完美!我假设它是下面的函数,但仍然不是 100% 确定。我来自 R 中的 Shiny,“回调”实际上是被包装的,所以很明显调用了哪个函数,但这里仍然对我提出了几个问题。我会接受你的帖子作为答案,因为这是一个很好的澄清和解释,非常感谢! 欢迎评论您的其他问题。我可以编辑帖子来回答他们 @DevinBurke & Ghost 这变成了一个非常好的帖子!如果您有后续问题,请考虑在新帖子中提问。多次跟进和编辑可以迅速将宝贵的资源,例如你们两个在这里吃过的,变成一团糟。期待你们俩的更多贡献!

以上是关于更新 Dash 中多个绘图的绘图的主要内容,如果未能解决你的问题,请参考以下文章

使用 Plotly-python 绘图后防止相机重置

如何更改我的 Dash Graph 的大小?

在背景中绘图

Python3绘图库Matplotlib(02)

matplotlib创建多个绘图区

Matplotlib 在 IDE (PyCharm) 中使用时不会更新绘图