Select columns to plot in y

I want to allow the user to choose which columns of a data frame one wants to see on y. I tried so much meanwhile but I still can’t get it to work. I followed Line charts in Python but there is actually not an example given according to my needs.
The possible columns to choose from are ['V+', 'V-', 'I_tube', 'I_heat'].
My code so far is:


app = Dash(__name__)

app.layout = html.Div(
                        style = {},
                        children = [
                                    html.H4('test'),
                                    dcc.Graph(id="graph"
                                              ),
                                    html.Br(),
                                    dcc.Checklist(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_tube', 'I_heat'],
                                                  value = ['V+'],
                                                  inline=True
                                                  ),
                                    ]
)


@app.callback(
              Output("graph", "figure"), 
              Input("signals", "value")
              )
def update_line_chart(signals):
    #df = all_df[all_df.columns == signals]
    df = all_df

    fig = px.line(df
                  , x = "time"
                  #, y = "I_heat"
                  #, y = df[signals]
                  #, y = signals['value']
                  #, y = df['value']
                  #, y = all_df.columns == signals['value']
                  , color = 'Device'
                  , hover_name="Device"
                  , template = 'plotly_dark'
                  )
    
    fig.update_layout(transition_duration=500)
    return fig

app.run_server()

I’m highly thankful for any input!

I think you should use dcc.RadioItems instead of dcc.Checklist. Because you want to see chart of each columns, not all.
You can do something as below:

import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import pandas as pd

df = px.data.gapminder().query("continent=='Oceania'")

app = dash.Dash(__name__, title='Dashboard', external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div([
    dcc.Graph(id='graph', 
              figure={}),
    dcc.RadioItems(id='radioitems', 
                  options=['lifeExp','gdpPercap'],
                 value='lifeExp')
])

@app.callback(Output('graph','figure'), 
              Input('radioitems','value'))

def update_graph(radioitems):
    fig = px.line(df, x="year", y=radioitems, color='country')
    return fig

if __name__ == "__main__":
    app.run_server(debug=False)

Thanks a lot, it’s working!

Just one (little?) comment: Indeed I would like to use Checklist instead of Radioitems, I guess? Or let’s say I would like to see two or more graphs in parallel, if possible? E.g. lifeExp and gdpPercap in parallel.
But when I simply replace Radioitems with Checklist I receive an error:

ValueError: All arguments should have the same length. The length of argument y is 9, whereas the length of previously-processed arguments [‘year’] is 24

Is there a(nother) way to do that?

If you want to do that, I think you should use pandas melt to transform your data. Year will be columns, columns will be rows.

Ok, thank you. I actually did that but how do I do the plotting now?

P.S.: Btw, I thought a bit about it: In my case, each column ['V+', 'V-', 'I_tube', 'I_heat'] provides the same amount of entries, so there shouldn’t be any mismatch or so?

Can you provide your dataframe? Or I think something as below should work:

import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
df = px.data.gapminder().query("continent=='Oceania'")
df = df[df['country'] == 'Australia']
df2 = df.melt(id_vars=['country','year'], value_vars=['lifeExp','gdpPercap'])

app = dash.Dash(__name__, title='Dashboard', external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div([
    dcc.Graph(id='graph', 
              figure={}),
    dcc.Checklist(id='checklist', 
                  options=['lifeExp','gdpPercap'],
                  value=[])
])

@app.callback(Output('graph','figure'), 
              Input('checklist','value'))

def update_graph(checklist):
    if checklist == []:
        fig = px.line(df2,x='year',y='value',color='variable')     
        return fig
    elif checklist != []:
        dff = df2[df2['variable'].isin(checklist)]
        fig = px.line(dff,x='year',y='value',color='variable')
        return fig

if __name__ == "__main__":
    app.run_server(debug=False)

Interesting to see how you solved that. Thank you very much, I’ll try to adjust this to my needs!

One last (tiny) question: Is it possible to give the graphs different shapes?
I tried it with:

    fig = px.line(df
                  , x = "time"
                  , y = signals
                  , color = 'Device'
                  #, line_dash = signals
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  )

but that doesn’t work (though I don’t understand why).

What does you mean about different shapes?

Means different appearances for each column, like in Linestyles — Matplotlib 3.7.1 documentation
Maybe even the same for markers but that would probably be quite the same.

The devices are automatically separated in colors thanks to df['Devices'].astype("category") and then using color = 'Device':

                 fig = px.line(df
                  , x = "time"
                  , y = signals
                  , color = 'Device'
                  #, line_dash = signals
                  , hover_name="Device"
                  , template = 'plotly_dark'
                  )

I guess line_dash = signals is not working accordingly as signals is not a column plus not categorical.

Can you provide your sample dataframe?

Hi,
sure, yes, sorry for the delay. Here is the link to download a .csv file of it: Filebin | pag2dnsixti4ce9a

Hi, do you have expected Output of Graph? Does this below match with your requirement?

Yes, that fits.

import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
df = pd.read_csv('out.csv')

df2 = df.melt(id_vars=['Device','time'], value_vars=['V+','V-','I_tube','I_heat'])

app = dash.Dash(__name__, title='Dashboard', external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = html.Div([
    dcc.Graph(id='graph', 
              figure={}),
    dcc.Checklist(id='checklist', 
                  options=['V+','V-','I_tube','I_heat'],
                  value=[])
])

@app.callback(Output('graph','figure'), 
              Input('checklist','value'))

def update_graph(checklist):
    if checklist == []:
        fig = px.line(df2,x='time',y='value',color='variable')
        fig.update_xaxes(type='category')
        return fig
    elif checklist != []:
        dff = df2[df2['variable'].isin(checklist)]
        fig = px.line(dff,x='time',y='value',color='variable')
        fig.update_xaxes(type='category')
        return fig

if __name__ == "__main__":
    app.run_server(debug=False)

You can use this code to run

Hi, thanks a lot again!

I also moved along with the input from your first contribution (the syntax seems easier to me, have to figure out, which I’ll use, I assume, your last code is more efficient) and this is what I have now:


# Initialise the app
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, title='Dashboard', external_stylesheets=external_stylesheets)                # Include css files


colors = {
    'background': '#000000',
    'text': '#f3ff00'
}

# Define the app
app.layout = html.Div(children = [
    
                            html.Div([
                                    html.H4('Dauertest'),
                                    html.Div(children = ""),

                                    # Draw graph
                                    dcc.Graph(id = 'General' 
                                              , figure={}
                                              ),
                                    ]),
                                    dcc.Checklist(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_tube', 'I_heat'],
                                                  value = ['V+', 'V-', 'I_tube'],
                                                  inline=True
                                                  ),
                                    html.Br(),
                                    html.Br(),
                                                                        
                            # New row
                            html.Div([
                                html.Div([                                    
                                    dcc.Graph(id = 'V+' 
                                              , figure={}
                                              ),
                                        ], className='six columns'),
                                html.Div([   
                                    dcc.Graph(id = 'V-' 
                                              , figure={}
                                              ),
                                        ], className='six columns'),
                                    ], className='row'),
                                    html.Br(),

                            # New row
                            html.Div([
                                html.Div([
                                    
                                            dcc.Graph(id = 'I_tube' 
                                                      , figure={}
                                                      ),
                                        ], className='six columns'),
                                html.Div([
                                            dcc.Graph(id = 'I_heat' 
                                                      , figure={}
                                                      ),
                                        ], className='six columns'),
                            ], className='row')
])


@app.callback(
              Output("General", "figure"), 
              Output("V+", "figure"), 
              Output("V-", "figure"), 
              Output("I_tube", "figure"), 
              Output("I_heat", "figure"), 
              Input("signals", "value")
              )
def update_line_chart(signals):
    fig_general = px.scatter(df
                  , x = "time"
                  , y = signals
                  , color = 'Device'
                  , symbol = signals
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  )

    
    fig_general.update_layout(
        transition_duration = 500
        , autosize = True
        , height = 700
        )
    
    
    fig_V_plus = px.scatter(df
                  , x = "time"
                  , y = "V+"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
    
    fig_V_minus = px.scatter(df
                  , x = "time"
                  , y = "V-"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
                      
    fig_I_heat = px.scatter(df
                  , x = "time"
                  , y = "I_heat"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
                      
    fig_I_tube = px.scatter(df
                  , x = "time"
                  , y = "I_tube"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
    
    return [fig_general, fig_V_plus, fig_V_minus, fig_I_heat, fig_I_tube]

# Run the app
if __name__ == "__main__":
    app.run_server(  )

I wonder whether there is an easy way to allow different marker symbols for in:

    fig_general = px.scatter(df
                  , x = "time"
                  , y = signals
                  , color = 'Device'
                  #, symbol = signals
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  )

symbol = signals unfortunately does not work. From the resulting error I understand that four options differ from the entire dataframe x and y receive but I actually don’t get the syntax issue in general.
If not, no worries, I’ll embed your code into mine, which is finally totally sufficient. I only would like to know whether there is a way as I got a bit of understanding about the code and how plotly/dash works (at least in this context, here :slight_smile: ).

Well, I think I’ll move on with your code anyway as it allows other features more easily, like creating several plots with a shared x-axis.
However, thanks a lot again!

Oh ok so now I understand what do you need. You can refer below code to make it.

import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
import pandas as pd
import plotly.express as px
df = pd.read_csv('out.csv')
df2 = df.melt(id_vars=['Device','time'], value_vars=['V+','V-','I_tube','I_heat'])


external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, title='Dashboard', external_stylesheets=external_stylesheets)                # Include css files


colors = {
    'background': '#000000',
    'text': '#f3ff00'
}

# Define the app
app.layout = html.Div(children = [
    
                            html.Div([
                                    html.H4('Dauertest'),
                                    html.Div(children = ""),

                                    # Draw graph
                                    dcc.Graph(id = 'General' 
                                              , figure={}
                                              ),
                                    ]),
                                    dcc.Checklist(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_tube', 'I_heat'],
                                                  value = ['V+', 'V-', 'I_tube'],
                                                  inline=True
                                                  ),
                                    html.Br(),
                                    html.Br(),
                                                                        
                            # New row
                            html.Div([
                                html.Div([                                    
                                    dcc.Graph(id = 'V+' 
                                              , figure={}
                                              ),
                                        ], className='six columns'),
                                html.Div([   
                                    dcc.Graph(id = 'V-' 
                                              , figure={}
                                              ),
                                        ], className='six columns'),
                                    ], className='row'),
                                    html.Br(),

                            # New row
                            html.Div([
                                html.Div([
                                    
                                            dcc.Graph(id = 'I_tube' 
                                                      , figure={}
                                                      ),
                                        ], className='six columns'),
                                html.Div([
                                            dcc.Graph(id = 'I_heat' 
                                                      , figure={}
                                                      ),
                                        ], className='six columns'),
                            ], className='row')
])


@app.callback(
              Output("General", "figure"), 
              Output("V+", "figure"), 
              Output("V-", "figure"), 
              Output("I_tube", "figure"), 
              Output("I_heat", "figure"), 
              Input("signals", "value")
              )
def update_line_chart(signals):
    df3=df2[df2['variable'].isin(signals)]
    fig_general = px.scatter(df3
                  , x = "time"
                  , y = 'value'
                  , color = 'Device'
                  , symbol = 'variable'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  )

    
    fig_general.update_layout(
        transition_duration = 500
        , autosize = True
        , height = 700
        )
    
    
    fig_V_plus = px.scatter(df
                  , x = "time"
                  , y = "V+"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
    
    fig_V_minus = px.scatter(df
                  , x = "time"
                  , y = "V-"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
                      
    fig_I_heat = px.scatter(df
                  , x = "time"
                  , y = "I_heat"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
                      
    fig_I_tube = px.scatter(df
                  , x = "time"
                  , y = "I_tube"
                  , color = 'Device'
                  , hover_name = "Device"
                  , template = 'plotly_dark'
                  ).update_layout(
                      transition_duration = 500
                      , autosize = True
                      )
    
    return [fig_general, fig_V_plus, fig_V_minus, fig_I_heat, fig_I_tube]
# Run the app
if __name__ == "__main__":
    app.run_server(debug=False, port=8054)

Awesome, thank you very much!

I don’t wanna stretch out your help but as you’re already quite familiar with my stuff I would like to make you aware of another concernI raised :slight_smile: : Use same x-axis (time) for multiple (sub)plots but keep y-axis independent