Python Plotly:如何使用类似于在图例中单击轨迹的按钮切换轨迹?
我正在使用python创建带有交互式绘图(无破折号)的独立html文件。我已经能够构建一个带有按钮的plotly plot,这些按钮可以切换plot中轨迹的可见性。但是,此功能也会从图例中删除轨迹。我希望能够保留图例的功能(单击单个轨迹以切换可见性),但也有一组按钮可将该功能扩展到我定义的一组轨迹 目标是能够将所有内容(或选定组)切换为不可见,但根据需要将该组中的单个项目添加回可见 下面是一个示例(使用vestland修改的代码)来显示我当前的尝试Python Plotly:如何使用类似于在图例中单击轨迹的按钮切换轨迹?,python,plotly,plotly-python,Python,Plotly,Plotly Python,我正在使用python创建带有交互式绘图(无破折号)的独立html文件。我已经能够构建一个带有按钮的plotly plot,这些按钮可以切换plot中轨迹的可见性。但是,此功能也会从图例中删除轨迹。我希望能够保留图例的功能(单击单个轨迹以切换可见性),但也有一组按钮可将该功能扩展到我定义的一组轨迹 目标是能够将所有内容(或选定组)切换为不可见,但根据需要将该组中的单个项目添加回可见 下面是一个示例(使用vestland修改的代码)来显示我当前的尝试 import numpy as np impo
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()
这个例子不符合我的要求。下面是一个屏幕截图,它看起来像什么
问题是,如果我使用其中一个按钮,它确实会隐藏所有其他轨迹,但它也会将它们从图例中删除,因此它们无法切换回可见状态
因此,我的问题是,在args列表/字典中是否有一个不同的值,可以为功能提供与只需单击图例中的跟踪匹配的值
有点相关,有什么方法可以获得每条跟踪的当前可见性状态吗?经过一番适当的搜索,我已经能够在Plotly论坛上找到它。我还没有找到列出所有这些选项的地方,但这将非常有帮助 在args字典中指定给“visible”的列表似乎不需要仅是布尔值。为了使项目在图例中可见但在绘图中隐藏,需要将值设置为“Legendolly”。然后仍可以单击图例条目以切换单个可见性。这回答了我问题的主旨
args = [{'visible': True}]
args = [{'visible': 'legendonly'}]
args = [{'visible': False}]
维斯特兰的回答有助于解决我问题的第二部分,只是修改了我想要的痕迹,其他一切都保持不变。事实证明,您可以将字典后面的索引列表传递给args,这些args将只应用于所提供索引处的跟踪。我在示例中使用列表理解来查找与给定名称匹配的跟踪。我还为每一列添加了另一个跟踪,以显示它如何适用于多个跟踪
args = [{'key':arg}, [list of trace indices to apply key:arg to]]
下面是目前正在工作的代码
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()
这提供了以下功能:
“全部”按钮可以切换所有记录道的可见性
每个“其他”按钮将仅切换具有匹配名称的跟踪。这些轨迹在图例中仍然可见,可以通过单击图例中的轨迹或再次单击按钮将其恢复为可见
点击“B”按钮后(两次点击arg2)
然后单击图例中的第一个B轨迹
为了能够在不影响其他跟踪的情况下打开和关闭任何跟踪,似乎每个按钮都必须包含一个更新单元。可能还有其他方法,但下面的代码片段将生成以下绘图: 图1-启动时选择所有 绘图2-
C
和D
已关闭
图3-所有关闭
图4-全部打开
完整代码:
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import datetime
import plotly.express as px
periods = 200
cols = list('ABCD')
np.random.seed(123)
df = pd.DataFrame(np.random.randint(-10, 12, size=(periods, len(cols))),
columns=cols)
datelist = pd.date_range(datetime.datetime(2020, 1, 1).strftime('%Y-%m-%d'),
periods=periods).tolist()
df['dates'] = datelist
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)
df.iloc[0] = 0
df = df.cumsum()
# # plotly
fig = go.Figure()
colors = px.colors.qualitative.Plotly
# set up multiple traces
for col in df.columns:
fig.add_trace(go.Scatter(x=df.index,
y=df[col],
name = col,
visible=True
)
)
um = [ {} for _ in range(len(df.columns)) ]
buttons = []
menuadjustment = 0.15
buttonX = -0.1
buttonY = 1 + menuadjustment
for i, col in enumerate(df.columns):
button = dict(method='restyle',
label=col,
visible=True,
args=[{'visible':True,
'line.color' : colors[i]}, [i]],
args2 = [{'visible': False,
'line.color' : colors[i]}, [i]],
)
# adjust some button features
buttonY = buttonY-menuadjustment
um[i]['buttons'] = [button]
um[i]['showactive'] = False
um[i]['y'] = buttonY
um[i]['x'] = buttonX
# add a button to toggle all traces on and off
button2 = dict(method='restyle',
label='All',
visible=True,
args=[{'visible':True}],
args2 = [{'visible': False}],
)
# assign button2 to an updatemenu and make some adjustments
um.append(dict())
um[i+1]['buttons'] = [button2]
um[i+1]['showactive'] = True
um[i+1]['y']=buttonY - menuadjustment
um[i+1]['x'] = buttonX
# add dropdown menus to the figure
fig.update_layout(showlegend=True, updatemenus=um)
# adjust button type
for m in fig.layout.updatemenus:
m['type'] = 'buttons'
f = fig.full_figure_for_development(warn=False)
fig.show()