Multiple traces plotly_express

I’m trying to plot the multiple traces on one plot using the plotly_express

import plotly_express as px

fig1 = px.scatter(df, x='date', y='cp_setting')
fig1.add_scatter(df, x='date', y='20m_critical_power')
fig1

but stumble upon this error:

    The 'cliponaxis' property must be specified as a bool
    (either True, or False)

What are the general recommendations on how to plot multiple traces with px?

1 Like

The way you’re trying to do it is the recommended way… @jmmease any thoughts about this error?

EDIT:

I would now actually recommend doing things like this

import plotly_express as px

px.scatter(df.melt(id_vars="date"), x='date', y='value', color='variable')
1 Like

Hi @sladkovm,

This is the recommended way to add traces. Could you include the full stack trace for the error you’re getting? Also, if you could write out a sample data frame that causes the error that would be helpful.

Thanks!
-Jon

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-17-d67da134c7b9> in <module>
      1 fig = px.scatter(_df, x='date', y='cp_setting')
----> 2 fig.add_scatter(_df, x='date', y='20m_critical_power')
      3 fig

~/.local/share/virtualenvs/cycling-analytics-o7NF_DiO/lib/python3.6/site-packages/plotly/graph_objs/_figure.py in add_scatter(self, cliponaxis, connectgaps, customdata, customdatasrc, dx, dy, error_x, error_y, fill, fillcolor, groupnorm, hoverinfo, hoverinfosrc, hoverlabel, hoveron, hovertemplate, hovertemplatesrc, hovertext, hovertextsrc, ids, idssrc, legendgroup, line, marker, mode, name, opacity, orientation, r, rsrc, selected, selectedpoints, showlegend, stackgaps, stackgroup, stream, t, text, textfont, textposition, textpositionsrc, textsrc, tsrc, uid, uirevision, unselected, visible, x, x0, xaxis, xcalendar, xsrc, y, y0, yaxis, ycalendar, ysrc, row, col, **kwargs)
   7492             ycalendar=ycalendar,
   7493             ysrc=ysrc,
-> 7494             **kwargs
   7495         )
   7496         return self.add_trace(new_trace, row=row, col=col)

~/.local/share/virtualenvs/cycling-analytics-o7NF_DiO/lib/python3.6/site-packages/plotly/graph_objs/__init__.py in __init__(self, arg, cliponaxis, connectgaps, customdata, customdatasrc, dx, dy, error_x, error_y, fill, fillcolor, groupnorm, hoverinfo, hoverinfosrc, hoverlabel, hoveron, hovertemplate, hovertemplatesrc, hovertext, hovertextsrc, ids, idssrc, legendgroup, line, marker, mode, name, opacity, orientation, r, rsrc, selected, selectedpoints, showlegend, stackgaps, stackgroup, stream, t, text, textfont, textposition, textpositionsrc, textsrc, tsrc, uid, uirevision, unselected, visible, x, x0, xaxis, xcalendar, xsrc, y, y0, yaxis, ycalendar, ysrc, **kwargs)
  37400         # ----------------------------------
  37401         _v = arg.pop('cliponaxis', None)
> 37402         self['cliponaxis'] = cliponaxis if cliponaxis is not None else _v
  37403         _v = arg.pop('connectgaps', None)
  37404         self['connectgaps'] = connectgaps if connectgaps is not None else _v

~/.local/share/virtualenvs/cycling-analytics-o7NF_DiO/lib/python3.6/site-packages/plotly/basedatatypes.py in __setitem__(self, prop, value)
   3164             # ### Handle simple property ###
   3165             else:
-> 3166                 self._set_prop(prop, value)
   3167 
   3168         # Handle non-scalar case

~/.local/share/virtualenvs/cycling-analytics-o7NF_DiO/lib/python3.6/site-packages/plotly/basedatatypes.py in _set_prop(self, prop, val)
   3405                 return
   3406             else:
-> 3407                 raise err
   3408 
   3409         # val is None

~/.local/share/virtualenvs/cycling-analytics-o7NF_DiO/lib/python3.6/site-packages/plotly/basedatatypes.py in _set_prop(self, prop, val)
   3400         validator = self._validators.get(prop)
   3401         try:
-> 3402             val = validator.validate_coerce(val)
   3403         except ValueError as err:
   3404             if self._skip_invalid:

~/.local/share/virtualenvs/cycling-analytics-o7NF_DiO/lib/python3.6/site-packages/_plotly_utils/basevalidators.py in validate_coerce(self, v)
    590             pass
    591         elif not isinstance(v, bool):
--> 592             self.raise_invalid_val(v)
    593 
    594         return v

~/.local/share/virtualenvs/cycling-analytics-o7NF_DiO/lib/python3.6/site-packages/_plotly_utils/basevalidators.py in raise_invalid_val(self, v, inds)
    275             typ=type_str(v),
    276             v=repr(v),
--> 277             valid_clr_desc=self.description()))
    278 
    279     def raise_invalid_elements(self, invalid_els):

ValueError: 
    Invalid value of type 'pandas.core.frame.DataFrame' received for the 'cliponaxis' property of scatter
        Received value:                                                date  cp_setting  \
date                                                              
2003-07-10 22:00:00+00:00 2003-07-10 22:00:00+00:00       220.0   
2003-07-11 22:00:00+00:00 2003-07-11 22:00:00+00:00       220.0   
2003-07-12 22:00:00+00:00 2003-07-12 22:00:00+00:00       220.0   
2003-07-13 22:00:00+00:00 2003-07-13 22:00:00+00:00       220.0   
2003-07-15 22:00:00+00:00 2003-07-15 22:00:00+00:00       220.0   

                           20m_critical_power  
date                                           
2003-07-10 22:00:00+00:00           162.56768  
2003-07-11 22:00:00+00:00           246.19832  
2003-07-12 22:00:00+00:00           209.03568  
2003-07-13 22:00:00+00:00           182.16999  
2003-07-15 22:00:00+00:00           125.85205  

    The 'cliponaxis' property must be specified as a bool
    (either True, or False)

I wonder if it has anything to do with a datetime, but the vanilla plotly way seems to work:

trace1 = go.Scatter(x=df.date, y=df.cp_setting, mode='lines', name='CP Setting')
trace2 = go.Scatter(x=df.date, y=df['20m_critical_power'], mode='markers', name='20m Power')
iplot(go.Figure([trace1, trace2]))

Ah sorry I didn’t see the df in your fig1.add_scatter(df, ... call!

add_scatter doesn’t have the same “data frame + column names” API as Plotly Express so here you’ll need to do something like fig.add_scatter(x=df.date, y=df.20m_critical_power).

1 Like

Thanks, this works. I like add_xxx API better. Does allow mixing columns from two different dataframes while plotting.

What about for adding traces after you’ve split data by facets?
For example:

import plotly_express as px
import pandas as pd

df = px.data.gapminder()
df_grouped = df.groupby(['continent','year'], as_index=False).mean()

px_plot = px.line(df_grouped, x='year', y='gdpPercap', color='continent', facet_row='continent')
# Plot before....
px_plot

for c in list(df_grouped.continent.unique()):
    continent_df = df_grouped.loc[df_grouped.continent==c, :].reset_index()
    px_plot.add_scatter(x=continent_df.year, y=continent_df.lifeExp*100, name=continent_df.continent[0])

# ...plot after
px_plot

They all get plotted in the first facet but I’m hoping to add a trace within each facet based off the facet attribute(s) and/or color in a dual axis fashion. Any suggestions?

PS Yes, this is a non-practical example, but was the easiest reproducible example to avoid sharing proprietary data

This is tricky at the moment but in a couple of weeks when Plotly.py v4 is released, with Plotly Express built-in as plotly.express you’ll be able to add row=n, col=m in your add_scatter() call to target a specific facet.

In the meantime, you’ll need to set the yaxis and xaxis attributes of your new traces to match whatever subplot you want to target.

1 Like

What if I want to add a line_3d?? fig does not have that property add_line_3d??

fig.add_scatter3d also does not work. It does not accept a dataframe as first argument. It would be nice if the api would be more consistent.

With version 4.8 of Plotly.py, you can now plot this kind of data directly from PX, with y=['cp_setting', '20m_critical_power']

1 Like