Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotly: How to select graph source using dropdown?

I'm trying to embed multiple, selectable graphs in a single figure using Plotly, using a dropdown figure. I followed the dropdown example from Plotly, but they only show how to change graph characteristics (like visible, or type), not the underlying data. In my situation, I have a static X-axis and want to change the Y-values. Here's a minimal working example that can be run in a jupyter notebook:

import plotly
from plotly import graph_objs as go, offline as po, tools
po.init_notebook_mode()

import numpy as np
import json

x = list(np.linspace(-np.pi, np.pi, 100))
values_1 = list(np.sin(x))
values_2 = list(np.tan(x))

line = go.Scatter(
    x=x,
    y=values_1
)

updatemenus = [
    {
        'buttons': [
            {
                'method': 'restyle',
                'label': 'Val 1',
                'args': [
                    {'y': json.dumps(values_1)},
                ]
            },
            {
                'method': 'restyle',
                'label': 'Val 2',
                'args': [
                    {'y': json.dumps(values_2)},
                ]
            }
        ],
        'direction': 'down',
        'showactive': True,
    }
]

layout = go.Layout(
    updatemenus=updatemenus,
)

figure = go.Figure(data=[line], layout=layout)

po.iplot(figure)

However, while the approach seems to work like advertised for general graph attributes (like 'visible'), when I use 'y', it produces a straight line, where y goes from 0 to len(y), instead of the actual data I gave it. Here are images of the initial render, and then what happens when I select the dropdown item for the Tan(X) graph, then go back to the Sin(X):

Initial graph

The result when I select Val 2

The result when I go back to Val 1

How do I embed the data for multiple graphs into a single figure so that the user can select which one they want to view?

like image 327
scnerd Avatar asked Sep 25 '17 17:09

scnerd


People also ask

What DCC dropdown?

dcc. Dropdown is a component for rendering a user-expandable dropdown.

What does Add_trace do in Plotly?

Adding Traces New traces can be added to a plot_ly figure using the add_trace() method. This method accepts a plot_ly figure trace and adds it to the figure. This allows you to start with an empty figure, and add traces to it sequentially.

What is XREF in Plotly?

By default, text annotations have xref and yref set to "x" and "y" , respectively, meaning that their x/y coordinates are with respect to the axes of the plot.


1 Answers

Updated answer using graph_objects:

As of version 4, you don't have to worry about offline versus online functionality. So drop the from plotly import graph_objs as go, offline as po and po.init_notebook_mode(), and just use import plotly.graph_objects as go. I've updated my original answer with a complete code snippet that shows the whole approach with multiple traces using plotly.graph_objects at the end. The solution to the question as it still stands will still be the same, namely:


'y' in updatemenus does not take a single list as an argument, but rather a list of lists like in 'y' = [values_1] where values_1 is a list in itself. So just replace your lines

  • {'y': json.dumps(values_1)}, and {'y': json.dumps(values_2)},

with

  • {'y': [values_1]}, and {'y': [values_2]},

to get these plots for the different options Val 1 and Val 2:


enter image description here

enter image description here


Some Details:

Values_1 is, unsurprisingly, a list of length 100 where each element is of type numpy.float. Replacing json.dumps(values_1) with values_1, and json.dumps(values_2) with values_2 will render the same plots as in your question. The reason why these plots are just straight lines, seems to be that it's the length of your lists that are being plotted, and not the values contained in that list. Or something to that effect.

Setting 'y' = values_1 is the same thing as assigning a single list to 'y'. But 'y' in updatemenus does not take a single list as an argument, but rather a list of lists like in 'y' = [values_1]. Why? Because you might want to plot multiple lists in the same figure like 'y' = [values_1, values_1b]. Have a look:

Plot for dropdown option Var 1:

enter image description here

Plot for dropdown option Var 2

enter image description here

Complete original code:

import plotly
from plotly import graph_objs as go, offline as po, tools
po.init_notebook_mode()

import numpy as np
import json

x = list(np.linspace(-np.pi, np.pi, 100))
values_1 = list(np.sin(x))
values_1b = [elem*-1 for elem in values_1]

values_2 = list(np.tan(x))
values_2b = [elem*-1 for elem in values_2]


line = go.Scatter(
    x=x,
    y=values_1
)

line2 = go.Scatter(
    x=x,
    y=values_1b
)


updatemenus = [
    {
        'buttons': [
            {
                'method': 'restyle',
                'label': 'Val 1',
                'args': [
                    {'y': [values_1, values_1b]},
                ]
            },
            {
                'method': 'restyle',
                'label': 'Val 2',
                'args': [
                    {'y': [values_2, values_2b]},
                ]
            }
        ],
        'direction': 'down',
        'showactive': True,
    }
]

layout = go.Layout(
    updatemenus=updatemenus,
)

figure = go.Figure(data=[line, line2], layout=layout)
po.iplot(figure)

Complete updated code:

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

# data
x = list(np.linspace(-np.pi, np.pi, 100))
values_1 = list(np.sin(x))
values_1b = [elem*-1 for elem in values_1]
values_2 = list(np.tan(x))
values_2b = [elem*-1 for elem in values_2]

# plotly setup]
fig = go.Figure()

# Add one ore more traces
fig.add_traces(go.Scatter(x=x, y=values_1))
fig.add_traces(go.Scatter(x=x, y=values_1b))

# construct menus
updatemenus = [{'buttons': [{'method': 'update',
                             'label': 'Val 1',
                             'args': [{'y': [values_1, values_1b]},]
                              },
                            {'method': 'update',
                             'label': 'Val 2',
                             'args': [{'y': [values_2, values_2b]},]}],
                'direction': 'down',
                'showactive': True,}]

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

Plot with version 4 default layout:

enter image description here

like image 195
vestland Avatar answered Oct 12 '22 20:10

vestland