5

I'm writing a small script to plot material data using plotly, I tried to use a dropdown to select which column of my dataframe to display. I can do this by defining the columns one by one but the dataframe will change in size so I wanted to make it flexible.

I've tried a few things and got to this;

for i in df.columns:
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=df.index, y=df[i]))

    fig.update_layout(
        updatemenus=[
            go.layout.Updatemenu(
                buttons=list([
                    dict(
                        args=["values", i],
                        label=i,
                        method="update"
                    ),
                ]),
                direction="down",
                pad={"r": 10, "t": 10},
                showactive=True,
                x=0.1,
                xanchor="left",
                y=1.1,
                yanchor="top"
            ),
        ]
    )
    fig.update_layout(
        annotations=[
            go.layout.Annotation(text="Material:", showarrow=False,
                             x=0, y=1.085, yref="paper", align="left")
        ]
    )

fig.show()

The chart shows the final column of the df, while dropdown only holds the last column header?

My data looks something like this, where i is the index, the chart and dropdown show column 'G';

i  A  B  C  D  E  F  G
1  8  2  4  5  4  9  7
2  5  3  7  7  6  7  3
3  7  4  9  3  7  4  6
4  3  9  3  6  3  3  4
5  1  7  6  9  9  1  9
0

1 Answer 1

4

The following suggestion should be exactly what you're asking for. It won't exceed the built-in functionalities to an extreme extent though, meaning that you can already subset your figure by clicking the legend. Anyway, let me know if this is something you can use or if it needs som adjustments.

Plot 1 - State of plot on first execution:

enter image description here

Click the dropdown in the upper left corner and select, D for example to get:

Plot 2 - State of plot after selecting D from dropdown:

enter image description here

Code:

# imports
import plotly.graph_objs as go
import pandas as pd

# data sample
df = pd.DataFrame({'i': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5},
                     'A': {0: 8, 1: 5, 2: 7, 3: 3, 4: 1},
                     'B': {0: 2, 1: 3, 2: 4, 3: 9, 4: 7},
                     'C': {0: 4, 1: 7, 2: 9, 3: 3, 4: 6},
                     'D': {0: 5, 1: 7, 2: 3, 3: 6, 4: 9},
                     'E': {0: 4, 1: 6, 2: 7, 3: 3, 4: 9},
                     'F': {0: 9, 1: 7, 2: 4, 3: 3, 4: 1},
                     'G': {0: 7, 1: 3, 2: 6, 3: 4, 4: 9}})
df=df.set_index('i')

# plotly figure setup
fig = go.Figure()

# one trace for each df column
for col in df.columns:
    fig.add_trace(go.Scatter(x=df.index, y=df[col].values,
                             name = col,
                             mode = 'lines')
                 )

# one button for each df column
updatemenu= []
buttons=[]
for col in df.columns:
    buttons.append(dict(method='restyle',
                        label=col,
                        args=[{'y':[df[col].values]}])
                  )

# some adjustments to the updatemenu
updatemenu=[]
your_menu=dict()
updatemenu.append(your_menu)
updatemenu[0]['buttons']=buttons
updatemenu[0]['direction']='down'
updatemenu[0]['showactive']=True

# update layout and show figure
fig.update_layout(updatemenus=updatemenu)
fig.show()
Sign up to request clarification or add additional context in comments.

2 Comments

That is about as close to perfect as I can hope for.. Ideally I'd like it to default to the first column only on the chart, but thats fine with me. Thank you again!
@Iceberg_Slim Happy to help. I'll try to look into that last detail tomorrow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.