0

So I am aware the "multi=True" will allow users to select more than one value from the dropdown box. However, I keep getting an error every time and I believe its due to the number of Y axises on my graph.

The code is below, and the goal is to select more than one things on the graph at once. Right now, my code is set to select to different y values set to the same x axis via two separate graphs (fig1 and fig2).Before, I had one graph with both y axis on it, but could not get the call back to address each one individually.

Any ideas on how to make this happen? Thanks in advance!

###THIS WILL LET ME DROP DOWN BUT TO SEPERATE GRAPHS AND WONT ALLOW ME TO HAVE BOTH DISPLAYED AT THE SAME TIME

import pandas as pd

fig1 = px.line(full_data, x = "Date", y = "Volume")
fig2 = px.line(full_data, x = "Date", y = "Price")

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px


# you need to include __name__ in your Dash constructor if
# you plan to use a custom CSS or JavaScript in your Dash apps
app = JupyterDash(__name__)

#---------------------------------------------------------------
app.layout = html.Div([
    html.Div([
        html.Label(['Full Chart']),
        dcc.Dropdown(
            id='my_dropdown',
            options=[
                     {'label': 'Price', 'value': 'Price'},
                     {'label': 'Volume', 'value': 'Volume'},
                     {'label': 'Positive Tweets', 'value': 'Positive Tweets'},
                     {'label': 'Negative Tweets', 'value': 'Negative Tweets'},
                     {'label': 'Neutral Tweets', 'value': 'Neutral Tweets'},
                     {'label': 'Total Number of Tweets', 'value': 'Total Number of Tweets'}
            ],
            value='Price',
            multi=True,
            clearable=False,
            style={"width": "50%"}
        ),
    ]),

    html.Div([
        dcc.Graph(id='the_graph')
    ]),

])

#---------------------------------------------------------------
@app.callback(
    Output(component_id='the_graph', component_property='figure'),
    [Input(component_id='my_dropdown', component_property='value')]
)

def update_graph(my_dropdown):
    if my_dropdown == 'Price':
        return fig1
    if my_dropdown == 'Volume':
        return fig2
etc for rest of the data...

<!-- begin snippet: js hide: false console: true babel: false -->

if __name__ == '__main__':
    app.run_server(debug=True, port = 9001)

2 Answers 2

2

First of all, in case of multi-dropdown menu, the value attribute inside the dropdown component should be a list and not a string (as you'll be selecting a list of options).
In order to customize each trace separately, you have to use graph_objects instead of Plotly express. The following code will update the figure with a new trace every time you'll select an option from the dropdown menu.

import pandas as pd
import numpy as np

# fig1 = px.line(full_data, x = "Date", y = "Volume")
# fig2 = px.line(full_data, x = "Date", y = "Price")

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go


# you need to include __name__ in your Dash constructor if
# you plan to use a custom CSS or JavaScript in your Dash apps
app = dash.Dash(__name__)


# Creating random DataFrame
columns = ['Price', 'Volume', 'Positive Tweets', 'Negative Tweets', 'Neutral Tweets', 'Total Number of Tweets']
np.random.seed(2019)
N = 10
rng = pd.date_range('2019-01-01', freq='MS', periods=N)
df = pd.DataFrame(np.random.rand(N, 6), columns=columns, index=rng)

#---------------------------------------------------------------
app.layout = html.Div([
    html.Div([
        html.Label(['Full Chart']),
        dcc.Dropdown(
            id='my_dropdown',
            options=[
                     {'label': 'Price', 'value': 'Price'},
                     {'label': 'Volume', 'value': 'Volume'},
                     {'label': 'Positive Tweets', 'value': 'Positive Tweets'},
                     {'label': 'Negative Tweets', 'value': 'Negative Tweets'},
                     {'label': 'Neutral Tweets', 'value': 'Neutral Tweets'},
                     {'label': 'Total Number of Tweets', 'value': 'Total Number of Tweets'}
            ],
            value=['Price'],
            multi=True,
            clearable=False,
            style={"width": "50%"}
        ),
    ]),

    html.Div([
        dcc.Graph(id='the_graph')
    ]),

])

#---------------------------------------------------------------
@app.callback(
    Output(component_id='the_graph', component_property='figure'),
    [Input(component_id='my_dropdown', component_property='value')]
)

def update_graph(my_dropdown):

    fig = go.Figure()

    for label in my_dropdown:
        fig.add_trace(go.Scatter(
            x = df.index,
            y = df[label],
            mode = 'lines',
            name = label
        ))
    return fig

if __name__ == '__main__':
    app.run_server(debug=True, port=9001)

The output of the code: Click Here

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! Now how would this work with the Yaxis being different values (volume in the billions, price in the thousands)?
It would work the same. The y-axis would automatically adjust itself to the values. Try replacing the dataframe with random values between thousand and a billion with following line of code: df = pd.DataFrame(([random.randrange(1000,1000000000) for i in range(6)] for i in range(N)), columns=columns, index=rng)
Nope I run into the same issue, it wont do something like Tweets and Volume because the y values are to different (thousands vs billions), I would have to add something to the function or the dcc.graph maybe that adds a y axis on the right side as well? (wont let me upload a pic to show)
0

final code and function, allowed me to use the drop down menu and added the additional y axis as well so multiple values can show properly at once. Thanks to Waleed Malik for the initial code!

import pandas as pd
​
import dash
from dash import dcc
from dash import  html
from dash.dependencies import Input, Output
import plotly.express as px
​
​
# you need to include __name__ in your Dash constructor if
# you plan to use a custom CSS or JavaScript in your Dash apps
app = JupyterDash(__name__)
​
app.layout = html.Div([
    html.Div([
        html.Label(['Full Chart']),
        dcc.Dropdown(
            id='my_dropdown',
            options=[
                     {'label': 'Price', 'value': 'Price'},
                     {'label': 'Volume', 'value': 'Volume'},
                     {'label': 'Positive Tweets', 'value': 'Positive Tweets'},
                     {'label': 'Negative Tweets', 'value': 'Negative Tweets'},
                     {'label': 'Neutral Tweets', 'value': 'Neutral Tweets'},
                     {'label': 'Total Number of Tweets', 'value': 'Total Number of Tweets'}
            ],
            value=['Price'],
            multi=True,
            clearable=False,
            style={"width": "50%"}
        ),
    ]),
​
    html.Div([
        dcc.Graph(id='the_graph')
    ]),
​
])
#---------------------------------------------------------------
​
#---------------------------------------------------------------
@app.callback(
    Output(component_id='the_graph', component_property='figure'),
    [Input(component_id='my_dropdown', component_property='value')]
)
​
def update_graph(my_dropdown):
​
    fig = make_subplots(specs=[[{"secondary_y": True}]])
     
​
    for label in my_dropdown:
        if label == "Volume":
            fig.add_trace(go.Bar(
            x = full_data["Date"],
            y = full_data["Volume"],
            #mode = "lines",
            name = label),
                secondary_y = True
        )
            
        else:
            fig.add_trace(go.Scatter(
            x = full_data["Date"],
            y = full_data[label],
            mode = 'lines',
            name = label,
        ))
    
        
    return fig
​
if __name__ == '__main__':
    app.run_server(debug=True, port = 9001)

enter image description here

Comments

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.