Apply dropdown menu value to only certain traces

#1

I’m new to plotly, so bear with me. I’m using plotly offline in Python. I’ve made a plot which shows four lines at a time. Two of those lines are fixed; the other two are based on the value chosen in a dropdown menu. I got this to work by setting

visible = [True, True] + [(True if j==i else False) for j in range(n)]*2

when specifying the visibility applied to the traces for menu option i. Here n is the number of options for the other two lines. This works because I’m setting the visibilities of lines (lineA, lineB, lineC1, lineC2, lineC3, lineD1, lineD2, lineD3), so that when option i=1 is chosen, (lineA, lineB, lineC1, lineD1) are visible.

What I want to do next is to plot three lines at a time, but where only one is constant. So now I’m in the case where the lines are (lineA, lineB1, lineB2, lineB3, lineC1, lineC2), and I want to control the B and C lines through separate dropdown menus. How can I do this? How do I tell a dropdown menu to only apply to certain traces? (This would also simplify my first plot, which I feel was an inelegant solution.) I feel like this should have something to do with controlling the menu’s callbacks, but I haven’t had much luck in finding a tutorial on that.

(PS: I know that this can be done through a single dropdown menu by going over all possible combinations of (A,B1,C1), (A,B1,C2), ... but the number of lines I have is 10 for B and 7 for C.)

#2

Hi @jareth.holt

It would be much easier to answer if you’d have a code example!
By the way, have you considered to use ipywidgets ?

BR, Alex

#3

Hi there again,

Im not sure I understand fully what you wanted to achieve but I have kind of a solution here with ipywidgets:

import plotly.graph_objs as go
import ipywidgets as widgets
import numpy as np

fig = go.FigureWidget()

fig.add_scatter(y=np.random.randn(10),name='lineA')

numofB = 10
numofC = 7

for name in ['lineB'+str(i) for i in range(1,numofB+1)]:
    fig.add_scatter(y=np.random.randn(10),name=name, visible=False)
    
for name in ['lineC'+str(i) for i in range(1,numofC+1)]:
    fig.add_scatter(y=np.random.randn(10),name=name, visible=False)

@widgets.interact(lineB=range(1,numofB+1), lineC=range(1,numofC+1))
def update_graph(lineB,lineC):
    with fig.batch_update():
        for i in range(1,len(fig.data)):
            if i != lineB and i != numofB+lineC:
                fig.data[i].visible=False
            else:
                fig.data[i].visible = True
fig

Dropdowns_ipywidgets_plotly_trace_visibility

1 Like
#4

Hey @Alexboiboi, thanks for the response! I have what I’ve done so far on my work computer, so I was going to wait until tomorrow to respond with some actual code. You did interpret what I wanted correctly, no worries there.

I have been using ipywidgets, actually, and was able to do what I wanted with that. This started with me exploring data visualization alternatives to matplotlib, and trying to decide between dedicating to Bokeh, plotly, or just ipywidgets+matplotlib. Thank you for this example combining widgets with plotly, I hadn’t considered that! In particular, I hadn’t come across fig.batch_update at any point so far.

I might write a bit more tomorrow if I have anything to add, but I think you’ve solved it pretty well.

#5

Thanks :wink:

BTW, fig.batch_update() is not really necessary here. The advantage to use it is just to have all the traces update at once and not one after the other. It just looks cleaner that way

Greets, Alex

1 Like