Plotly: How to give different label names in a dropdown menu?

邮差的信 提交于 2021-02-07 20:06:11

问题


I was learning plotly dropdown menu and stumbled on a label problem.

Question

  • How to show labels sin and sin-1 when selected Sine. And show labels tan and tan-1 when selected Tan?

MWE

# imports
import plotly.graph_objects as go
import numpy as np

# data
x = np.linspace(-np.pi, np.pi, 100)

y1 = np.sin(x)
y1b = y1-1

y2 = np.tan(x)
y2b = y2-1

# plotly setup
fig = go.Figure()

# Add one ore more traces
fig.add_traces(go.Scatter(x=x, y=y1,name='sin'))
fig.add_traces(go.Scatter(x=x, y=y1b,name='sin - 1'))

fig.add_traces(go.Scatter(x=x, y=y2,name='tan'))
fig.add_traces(go.Scatter(x=x, y=y2b,name='tan - 1'))

# construct menus
updatemenus = [{'buttons': [{'method': 'update',
                             'label': 'Sine',
                             'args': [{'y': [y1, y1b]},]
                              },
                            {'method': 'update',
                             'label': 'Tan',
                             'args': [
                                 {'y': [y2, y2b],'label':['a','b']},
                             ]}
                           ],
                'direction': 'down',
                'showactive': True,}]

# update layout with buttons, and show the figure
fig.update_layout(updatemenus=updatemenus)
fig.show()

output


回答1:


Here's a generic helper function that you could use:

# Helper functions to create the appropriate buttons
def makePlotButtons(options, nTracesPerOption=1):    
    buttons = []
    for i, opt in enumerate(options):
        visibleArr = np.full((nTracesPerOption*len(options),), 
                             False, dtype=bool)
        
        startIdx = nTracesPerOption*i
        for idx in range(nTracesPerOption):
            visibleArr[startIdx + idx] = True
            
        buttons.append(dict(label=str(opt),
                            method='restyle',
                            args=[{'visible': list(visibleArr)}]))    # 'Visible' arg determines which plots are shown 
                                                                      # depending on which dropdown is selected 
    return buttons

where options is a list of strings and nTracesPerOption is how many traces you have per option. In the case of your questions, your options parameter would be ['Sine', 'Tan'] and nTracesPerOption is 2 (e.g. for sin and sin - 1).

Then in the MWE you provided, you would update the buttons field in your updatemenus variable to makePlotButtons(options, 2)




回答2:


For challenges such as this I've pretty much moved on to using Dash, so my abilites when it comes to specifying dropdown buttons like this is a bit rusty. So you'll have to forgive me because the following suggestion will only be a good solution if you stick to switching between Sine and Tan for the dropdown options. And select Sine as your first option. If you do, then:

1. Clicking Sine will give you this:

2. Clicking Tan will give you this:

3. And clicking Sine for the second time will give you this again:

And on and on it spins...

And notice how the legend shows only traces for your selected categories. This has been made possible through specifying which traces to restyle by specifying them trough their position in fig.data using integers [0, 1] and [2, 3] for the different buttons. The toggle functionality has been made possible using the args2 attribute. You can see all details in the complete code snippet below.

So why is this not a perfect solution??

  1. The button label shows some weire behavior where Sine disappears.

  2. If you select Tan first then... Try for yourself and see =)

Anyway, if other options turn out to be too complex or have other shortcomings, maybe you or other readers figure out how to make this suggestion meet your requirements 100%.

Complete code:

# imports
import plotly.graph_objects as go
import numpy as np

# data
x = np.linspace(-np.pi, np.pi, 100)

y1 = np.sin(x)
y1b = y1-1

y2 = np.tan(x)
y2b = y2-1

# plotly setup
fig = go.Figure()

# Add one ore more traces
fig.add_traces(go.Scatter(x=x, y=y1,name='sin'))
fig.add_traces(go.Scatter(x=x, y=y1b,name='sin - 1'))

fig.add_traces(go.Scatter(x=x, y=y2,name='tan'))
fig.add_traces(go.Scatter(x=x, y=y2b,name='tan - 1'))

# construct menus
updatemenus = [{'buttons': [{'method': 'restyle',
                             'label': 'Sine',
                             'args': [{'y': [y1, y1b],
                                       'label':'Sine',
                                       'name':['sin', 'sin - 1'],
                                       'visible': True}, [0, 1]],
                             'args2': [{'y': [y1, y1b],
                                       'visible': False}, [2, 3]]
                              },
                            
                            {'method': 'restyle',
                             'label': 'Tan',
                             'args': [{'y': [y2, y2b],
                                       'name': ['tan', 'tan - 1'],
                                       'visible':True}, [0, 1]],
                             'args2': [{'y': [y2, y2b],
                                       'visible':False}, [2, 3]],
                             }
                           ],
                'direction': 'down',
                'showactive': True,}]

# update layout with buttons, and show the figure
fig.update_layout(updatemenus=updatemenus)
fig.show()



回答3:


I got the following answer as suggested by @Jacob K

# imports
import plotly.graph_objects as go
import numpy as np

# data
x = np.linspace(-np.pi, np.pi, 100)


# plotly setup
fig = go.Figure()

# Add traces
fig.add_traces(go.Scatter(x=x, y=np.sin(x),name='sin'))
fig.add_traces(go.Scatter(x=x, y=np.sin(x)-1,name='sin - 1'))

fig.add_traces(go.Scatter(x=x, y=np.cos(x),name='cos'))
fig.add_traces(go.Scatter(x=x, y=np.cos(x)-1,name='cos - 1'))

fig.add_traces(go.Scatter(x=x, y=np.tan(x),name='tan'))
fig.add_traces(go.Scatter(x=x, y=np.tan(x)-1,name='tan - 1'))

# construct menus
# Helper functions to create the appropriate buttons
def makePlotButtons(options, nTracesPerOption=1):    
    buttons = []
    for i, opt in enumerate(options):
        visibleArr = np.full((nTracesPerOption*len(options),), 
                             False, dtype=bool)
        
        startIdx = nTracesPerOption*i
        for idx in range(nTracesPerOption):
            visibleArr[startIdx + idx] = True
            
        buttons.append(dict(label=str(opt),
                            method='restyle',
                            args=[{'visible': list(visibleArr)}]))    # 'Visible' arg determines which plots are shown 
                                                                      # depending on which dropdown is selected 
    return buttons

# update layout with buttons, and show the figure
updatemenus = [{'buttons': makePlotButtons(['Sine','Cosine', 'Tan'], 2),
                'direction': 'down',
                'showactive': True,}]


fig.update_layout(updatemenus=updatemenus)
fig.show()

and got following output



来源:https://stackoverflow.com/questions/65605076/plotly-how-to-give-different-label-names-in-a-dropdown-menu

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!