Plotly:如何使用类似于在图例中单击它们的按钮来切换轨迹? [英] Plotly: How to toggle traces with a button similar to clicking them in legend?

查看:27
本文介绍了Plotly:如何使用类似于在图例中单击它们的按钮来切换轨迹?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 python 并使用交互式绘图(无 Dash)创建独立的 html 文件.我已经能够构建一个带有按钮的情节图,这些按钮可以切换图中轨迹的可见性.但是,此功能也会从图例中删除痕迹.我想要的是能够保留图例的功能(单击单个轨迹以切换可见性),但也有一组按钮可以将该功能扩展到我定义的一组轨迹.

目标是能够将所有内容(或选择的组)切换为不可见,但根据需要将该组中的单个项目添加回可见.

下面是一个例子(使用来自

问题是,如果我使用其中一个按钮,它会隐藏所有其他痕迹,但也会将它们从图例中删除,因此它们无法切换回可见状态.

所以我的问题变成了,在 args 列表/字典中是否有一个不同的值可以让功能与简单地点击图例中的轨迹相匹配?

有点相关,有没有办法获得每个跟踪的当前可见状态?

解决方案

经过一番搜索,我终于弄清楚了,感谢

点击B"后按钮(两次点击 arg2).

然后在单击图例中的第一个 B 迹线之后.

I'm using python and creating standalone html files with interactive plots (no Dash). I have been able to build a plotly plot with buttons that can toggle the visibility of traces in the plot. However, this functionality removes the traces from the legend as well. What I would like is to be able to keep the functionality of the legend (click a single trace to toggle visibility) but also have a set of buttons that extends that functionality to a group of traces that I define.

The goal is to be able toggle everything (or a select group) to invisible but add individual items from that group back to visible as needed.

Below is an example (using modified code from this answer by vestland) to show what I am currently attempting.

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import datetime

# mimic OP's datasample

NPERIODS = 200

np.random.seed(123)
df = pd.DataFrame(np.random.randint(-10, 12, size=(NPERIODS, 4)),
                  columns=list('ABCD'))
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),
                         periods=NPERIODS).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum()

# set up multiple traces
traces = []
buttons = []
for col in df.columns:
    traces.append(go.Scatter(x=df.index,
                            y=df[col],
                            visible=True,
                            name=col)
                )
    buttons.append(dict(method='update',
                        label=col,
                        visible=True,
                        args=[{'visible':[x == col for x in df.columns]}],
                        args2=[{'visible':[x != col for x in df.columns]}]
                        )
                )

# create the layout 
layout = go.Layout(
    updatemenus=[
        dict(
            type='buttons',
            direction='right',
            x=0.7,
            y=1.3,
            showactive=True,
            buttons=buttons
        )
    ],
    title=dict(text='Toggle Traces',x=0.5),
    showlegend=True
)

fig = go.Figure(data=traces,layout=layout)

# add dropdown menus to the figure
fig.show()

That example does not work how I would like. Below is a screenshot of what it looks like at first.

The problem is that if I use one of those buttons, it does hide all the other traces but it also removes them from the legend so they can't be toggled back to visible.

So my question becomes, is there a different value in the args list/dictionary that can be given for the functionality to match that of simply clicking a trace in the legend?

Sort of related, is there some way to get the current state of visibility for each trace?

解决方案

After a decent bit of searching, I have been able to figure it out thanks to this answer on the Plotly forum. I have not been able to find somewhere that lists all of these options yet, but that would be very helpful.

It appears that the list given to 'visible' in the args dictionary does not need to be only booleans. In order to keep the items visible in the legend but hidden in the plot, you need to set the values to 'legendonly'. The legend entries can then still be clicked to toggle individual visibility. That answers the main thrust of my question.

args = [{'visible': True}]
args = [{'visible': 'legendonly'}]
args = [{'visible': False}]

Vestland's answer helped solve the second part of my question, only modifying the traces I want and leaving everything else the same. It turns out that you can pass a list of indices after the dictionary to args and those args will only apply to the traces at the indices provided. I used list comprehension in the example to find the traces that match the given name. I also added another trace for each column to show how this works for multiple traces.

args = [{'key':arg}, [list of trace indices to apply key:arg to]]

Below is the now working code.

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import datetime

# mimic OP's datasample

NPERIODS = 200

np.random.seed(123)
df = pd.DataFrame(np.random.randint(-10, 12, size=(NPERIODS, 4)),
                  columns=list('ABCD'))
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),
                         periods=NPERIODS).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum()

# set up multiple traces
traces = []
buttons = []
for col in df.columns:
    traces.append(go.Scatter(x=df.index,
                            y=df[col],
                            visible=True,
                            name=col)
                )
    traces.append(go.Scatter(x=df.index,
                y=df[col]+20,
                visible=True,
                name=col)
    )
    buttons.append(dict(method='restyle',
                        label=col,
                        visible=True,
                        args=[{'visible':True},[i for i,x in enumerate(traces) if x.name == col]],
                        args2=[{'visible':'legendonly'},[i for i,x in enumerate(traces) if x.name == col]]
                        )
                )

allButton = [
    dict(
        method='restyle',
        label=col,
        visible=True,
        args=[{'visible':True}],
        args2=[{'visible':'legendonly'}]
    )
]

# create the layout 
layout = go.Layout(
    updatemenus=[
        dict(
            type='buttons',
            direction='right',
            x=0.7,
            y=1.3,
            showactive=True,
            buttons=allButton + buttons
        )
    ],
    title=dict(text='Toggle Traces',x=0.5),
    showlegend=True
)

fig = go.Figure(data=traces,layout=layout)

# add dropdown menus to the figure
fig.show()

This gives the following functionality:

the "All" button can toggle visibility of all traces.

Each other button will only toggle the traces with the matching name. Those traces will still be visible in the legend and can be turned back to visible by clicking on them in the legend or clicking the button again.

After clicking the "B" button (twice to hit arg2).

And then after clicking the first B trace in the legend.

这篇关于Plotly:如何使用类似于在图例中单击它们的按钮来切换轨迹?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆