How to distinguish columns / variabls in go.scattergl() in means of color?

Hi there,

I would like to use go.Scattergl() instead of px.scatter() but I’m not sure how to enter the variables now. Simply replacing didn’t work and it seems like the data sets have to be addressed differently?
I want to separate columns (indicated by signals) by color and devices (by shape or whatever).
Thanks a lot in advance!

At the moment I have

    fig_general = px.scatter(df3
                              , x = "time"
                              , y = 'value'
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Device"
                              , template = 'plotly_dark'
                              #, marginal_y="rug"
                              ).update_layout(
                                              transition_duration = 500
                                              , autosize = True
                                              , height = 700
                                              )

which I would like to replace with go.Scattergl(). I tried

    fig_general = go.Figure()
    fig_general.add_trace(
                            go.Scattergl(
                              x = df3["time"]
                              , y = df3['value']
                              , fill = df3['Device']
                              , template = 'plotly_dark'
                              )
    )

which results in

self["fill"] = _v
(...)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

edit: I figured out that


    fig_general = go.Figure()
    fig_general.add_trace(
                            go.Scattergl(
                              x = df3["time"]
                              , y = df3['value']
                              )
    )

generates at least a plot. But it doesn’t distinguish between the selected columns, probably because of the missing fill = command or the like. But it doesn’t work as in px.scatter(). Any idea?

Here is the entire code:


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


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

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

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

                                    dcc.Graph(id = 'General' 
                                              , figure={}
                                              ),
                                    ]),
                                    dcc.Checklist(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_A', 'I_fil'],
                                                  value = ['V+', 'V-'],
                                                  inline=True
                                                  ),
                                    html.Br(),
                                    html.Br(),
                                                                        
                            html.Div([
                                html.Div([                 
                                    dcc.Graph(id = 'shared' 
                                              , figure={}
                                              ),
                                        ], className='twelve columns'),
                                    ], className='row')
])


@app.callback(
              Output("General", "figure"), 
              Output("shared", "figure"), 
              Input("signals", "value")
              )
def update_line_chart(signals):
    df3=df2[df2['variable'].isin(signals)]

    fig_general = go.Figure()
    fig_general.add_trace(
                            go.Scattergl(
                                data = df3
                              , x = "time"
                              , y = 'value'
                              , color = 'Device'
                              , symbol = 'variable'
                              , hover_name = "Device"
                              , template = 'plotly_dark'
                              #, marginal_y="rug"
                              )
    )


    fig_shared = make_subplots(rows = 4
                               , cols = 1
                               , shared_xaxes=True
                               , vertical_spacing=0.05
                               )
    
    fig_shared.add_trace(go.Scattergl(
                                    x = all_df['time']
                                    , y = all_df['V+']
                                    , mode = "markers"
                                    , name="V+"
                                    , connectgaps = False
                                    , marker=dict(
                                                    symbol = "circle"
                                                    )
                                    )
                          , row=4
                          , col=1
                          )
    
    fig_shared.add_trace(go.Scattergl(
                                    x = all_df['time']
                                    , y = all_df['V-']
                                    , name="V-"
                                    , mode = "markers"
                                    , marker=dict(
                                                  symbol = "star"                
                                                  )
                                    )
                        , row=3
                        , col=1
                        )
    
    fig_shared.add_trace(go.Scattergl(
                                    x = all_df['time']
                                    , y = all_df['I_A']
                                    , name="I_A"
                                    , mode = "markers"
                                    , marker=dict(
                                                  symbol = "diamond"                
                                                  )
                                    )
                        , row=2
                        , col=1
                        )
    
    fig_shared.add_trace(go.Scattergl(
                                    x = all_df['time']
                                    , y = all_df['I_fil']
                                    , name="I_fil"
                                    , mode = "markers"
                                    , marker=dict(
                                                  symbol = "x"                
                                                  )
                                    )
                        , row=1
                        , col=1
                        )
    
    fig_shared.update_layout(
                            height= 1000
                            , width = 1900
                            , title_text = ""
                            , template = 'plotly_dark'
                            )

    fig_shared.show()
    
    fig_shared['layout']['yaxis']['title'] = 'I_fil / A'
    fig_shared['layout']['yaxis2']['title'] = 'I_A / A'
    fig_shared['layout']['yaxis3']['title'] = 'V- / V'
    fig_shared['layout']['yaxis4']['title'] = 'V+ / V'
    
    
    return [fig_general, fig_shared]



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

I hope I didn’t remove anything necessary… Here is the data set: Filebin | pag2dnsixti4ce9a

I stumbled over How to add categorical color legend for scatter plot created by graph_objects - #4 by ljam which looks alike but I can’t adjust it to my needs.

Hi @DeLaRiva these two code snippets create the same chart:

import pandas as pd
import plotly.graph_objects as go
import plotly.express as px

df = pd.read_csv('out.csv')

fig_px = px.scatter(
    df,
    x="time"
    y='V+',
    color='Device',
    hover_name="Device",
    template='plotly_dark'
  )

# use of plotly.graph_objects
gb = df.groupby('Device')

fig_go = go.Figure()

for name, group in gb:
    fig_go.add_scattergl(
            x=group["time"],
            y=group['V+'],
            name=name,
            mode='markers',
      )
fig_go.update_layout(
    legend={"title":"Device"}, 
    template='plotly_dark'
)
1 Like

Thank you very much! Will try it out asap!

But as far as I understand your code, it’s plotting V+ only, or? I would like to plot the four variables V+, V-, I_A, I_fil in parallel (e.g. with different shapes) plus distinguished by 'Device'.

Hi @DeLaRiva, it would be good if you asked for items which are actualle in your csv :wink:

Here an example:

cats = ['V+', 'V-', 'I_tube', 'I_heat']
colors =  iter(['red', 'blue', 'green', 'gold'])

gb = df.groupby('Device')

fig_go = go.Figure()

for name, group in gb:
    color = next(colors)
    for marker, cat in zip(['cross', 'circle', 'diamond', 'square'], cats):
        fig_go.add_scattergl(
                x=group["time"],
                y=group[cat],
                name=name,
                mode='markers',
                marker=dict(symbol=marker, color=color),
                line_color=color
          ),
fig_go.update_layout(
    legend={"title":"Device"}, 
    template='plotly_dark'
)

A note: I would consider separating the devices from the “variabels” because it’s really hard to distinguish the markers as the points are quite dense.

1 Like

Yeah, sorry, I renamed them… but thanks a lot for the code! Could you please show me how the plot looks for you?
The code is working but I’m not sure whether it’s correct? In my case the legend provides four items for the same device with four different shapes and the colors are all green.

Yes, the chart is correct. The colors reflect the different devices, the symbols reflect the different categories like you detailed above.

This however does not seem to be what you expected :rofl:

Hmmm.

Maybe instead of trying to use next on the colors, you alter your code to this.

for i in range(len(gb)):
    name, group = gb[i]
    color = colors[i]
    marker = markers[i]
    cat = cats[i]

Just define markers outside like you did the others. And bring your scattergl definition up one level to be outside the second for loop.

And also leave your colors as a regular list.

1 Like