Plotly:更新菜单的按钮如何真正起作用?

2022-01-21 00:00:00 python plotly

问题描述

我为什么想知道?

这似乎是一个非常简单的问题,但我在使用下拉菜单编辑具有多条轨迹的图形时遇到了一些困难,所以我真的很想确保我了解 plotlys 下拉菜单的内部工作原理,更新菜单和按钮 100% 正确.因此,如果有人能抽出时间来看看下面的示例,那就太好了.

This may seem like a very simple question, but I'm having some difficulties editing figures with multiple traces using dropdownmenus, so I'm really eager to make sure that I'm understanding the inner workings of plotlys dropdown menus, update menus and buttons 100% correct. So it would be great if someone could find the time to take a look at the example below.

有什么问题?

考虑以下由以下代码片段生成的简单图形:

Consider the following simple plotly figure produced by the code snippet below:

情节1:

代码 1:

# imports
import plotly.graph_objs as go
import pandas as pd
import numpy as np

# data
df1 = pd.DataFrame({'index': ['1','2','3'], 'A': [10,10,12], 'B': [11,11,11]})
df2 = pd.DataFrame({'index': ['1','2','3'], 'A': [10,10,10], 'B': [11,11,12]})

# plotly figure setup
fig=go.Figure()
fig.add_trace(go.Scatter(x=df1['index'], y=df1['A'], mode='lines'))
fig.add_trace(go.Scatter(x=df1['index'], y=df1['B'], mode='lines'))

#f=fig.to_dict()
fig.show()

现在我想用 df2['A']=[10 替换蓝线 df1['A']=[10,10,12] 的数据,10,10],同时将红线df1['B']=[11,11,11]的数据替换为df1['B']=[11,11,11].

Now I'd like to replace the data for the blue line df1['A']=[10,10,12] with df2['A']=[10,10,10], and at the same time replace the data for the red line df1['B']=[11,11,11] with df1['B']=[11,11,11].

我可以通过引入这样的下拉菜单轻松做到这一点:

And I can easily do so by introducing a dropdown menu like this:

情节 2 - 下拉菜单 = df1:

情节 3 - 下拉菜单 = df2

代码 2 - 与代码 1 相同,但添加了菜单:

# imports
import plotly.graph_objs as go
import pandas as pd
import numpy as np

# data
df1 = pd.DataFrame({'index': ['1','2','3'], 'A': [10,10,12], 'B': [11,11,11]})
df2 = pd.DataFrame({'index': ['1','2','3'], 'A': [10,10,10], 'B': [11,11,12]})

# plotly figure setup
fig=go.Figure()
fig.add_trace(go.Scatter(x=df1['index'], y=df1['A'], mode='lines'))
fig.add_trace(go.Scatter(x=df1['index'], y=df1['B'], mode='lines'))

f=fig.to_dict()
#fig.show()

buttons=list([dict(args=[{'y':[df1['A'],df1['B']],
                           #'type':'scatter',
                        }],
                    
                   label="df1",
                   method="restyle"
                ),
                dict(args=[{'y':[df2['A'], df2['B']],
                           #'type':'scatter',
                           #'mode':'markers'
                          }],
                    
                    label="df2",
                    method="restyle"
                )
            ])

fig.update_layout(
    updatemenus=[
        go.layout.Updatemenu(
            buttons=buttons,
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=-0.25,
            xanchor="left",
            y=1,
            yanchor="top"
        ),
    ]
)

fig.show()


它是如何工作的?

现在让我们看一下在引入下拉菜单之前该图的结构.我们可以通过查看变量 f=fig.to_dict() 来做到这一点.这是该字典的最上面几行:

Now let's take a look at how the figure was structured before the dropdown menu was introduced. We can do so by lookingat the variable f=fig.to_dict(). Here are the top lines of that dict:

  {'data': [{'mode': 'lines',
   'x': array(['1', '2', '3'], dtype=object),
   'y': array([10, 10, 12], dtype=int64),
   'type': 'scatter'},
  {'mode': 'lines',
   'x': array(['1', '2', '3'], dtype=object),
   'y': array([11, 11, 11], dtype=int64),
   'type': 'scatter'}]

这里可以看到'y'出现了两次:

Here you can see that 'y' appears twice:

# 1
'y': array([10, 10, 12], dtype=int64),

# 2
'y': array([10, 10, 12], dtype=int64),

这让我有点困惑,因为我们可以通过仅引用 both 来更改 y 的值一次进入下拉菜单中的按钮:

And this leaves me a bit puzzled, since we're able to change both values for y by only referencing it once int the button in the dropdown menu:

# from the snippet Code 2 above:
dict(args=[{'y':[df2['A'], df2['B']]}]


最后,主要问题:

现在很明显,它的工作方式是更新菜单从按钮中获取 y 的值,查找每个 'y' 键 将列表[df2['A'], df2['B']]中的元素一一插入,只要有ys 来填写.但这真的是这里发生的事情吗?如果你们中的任何人能够提供一个自信的'YES',我会很高兴,但我真的希望有一个自信的'NO'和一个很少有关于这些东西是如何真正组合在一起的细节.

Now it seems very apparent that the way this works is that the updatemenu takes the value for y from the button, looks up every 'y' key in the figure and inserts the elements in the list [df2['A'], df2['B']] one by one as long as there are ys to fill. But is that really exactly what's happening here? If any of you are able to deliver a confident 'YES' I'd be quite happy with that, but I'm really hoping for a confident 'NO' and a few details on how these things are really put together.


解决方案

好问题!真正的工作原理是使用 method 属性指定要应用的底层 plotly.js Javascript 函数的名称,其参数来自 <代码>参数.所以你实际上是在调用 JS 函数 Plotly.restyle(<fig>, {'y': <whatever>}).这意味着您正在寻找的文档在这里:https://plot.ly/javascript/plotlyjs-function-reference/ 更具体地说是 restyle 函数,这里是 https://plot.ly/javascript/plotlyjs-function-reference/#plotlyrestyle

Great question! How things really work is that with the method attribute you're specifying the name of the underlying plotly.js Javascript function you want to apply, and its arguments are drawn from args. So you're really calling the JS function Plotly.restyle(<fig>, {'y': <whatever>}). This means that the documentation you're seeking is here: https://plot.ly/javascript/plotlyjs-function-reference/ and more specifically the restyle function which is here https://plot.ly/javascript/plotlyjs-function-reference/#plotlyrestyle

如你所见:

注意,未指定跟踪索引假定您要重新设置所有跟踪的样式.

Note, leaving the trace indices unspecified assumes that you want to restyle all the traces.

相关文章