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?

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

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.