1

I am trying to create subplots with plotly express. I tried using make_subplots to achieve this. Here is my code

import plotly.express as px
from plotly.subplots import make_subplots

df['upload_date'] = pd.to_datetime(df['upload_date'])
df.index = df['upload_date']

df_grouped_by_year = df.groupby([pd.Grouper(freq="y"), 'category']).mean()
df_grouped_by_year = df_grouped_by_year.reset_index()

fig = make_subplots(rows=2, cols=1)

trace1 = px.line(df_grouped_by_year, x='upload_date', y="like_count", color='category')
trace2 = px.line(df_grouped_by_year, x='upload_date', y="dislike_count", color='category')

fig.add_trace(trace1, row=1, col=1)
fig.add_trace(trace2, row=2, col=1)

fig.show()

This is what df_grouped_by_year data looks like enter image description here

But the code gives me the following error

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [30], in <module>
      3 trace1 = px.line(df_grouped_by_year, x='upload_date', y="like_count")
      4 trace2 = px.line(df_grouped_by_year, x='upload_date', y="dislike_count")
----> 6 fig.add_trace(trace1, row=1, col=1)
      7 fig.add_trace(trace2, row=2, col=1)
      9 fig.show()

File ~/miniforge3/envs/capstone/lib/python3.10/site-packages/plotly/basedatatypes.py:2099, in BaseFigure.add_trace(self, trace, row, col, secondary_y, exclude_empty_subplots)
   2090         self.add_trace(
   2091             trace,
   2092             row=r,
   (...)
   2095             exclude_empty_subplots=exclude_empty_subplots,
   2096         )
   2097     return self
-> 2099 return self.add_traces(
   2100     data=[trace],
   2101     rows=[row] if row is not None else None,
   2102     cols=[col] if col is not None else None,
   2103     secondary_ys=[secondary_y] if secondary_y is not None else None,
   2104     exclude_empty_subplots=exclude_empty_subplots,
   2105 )

File ~/miniforge3/envs/capstone/lib/python3.10/site-packages/plotly/basedatatypes.py:2183, in BaseFigure.add_traces(self, data, rows, cols, secondary_ys, exclude_empty_subplots)
   2115 """
   2116 Add traces to the figure
   2117 
   (...)
   2179 Figure(...)
   2180 """
   2182 # Validate traces
-> 2183 data = self._data_validator.validate_coerce(data)
   2185 # Set trace indexes
   2186 for ind, new_trace in enumerate(data):

File ~/miniforge3/envs/capstone/lib/python3.10/site-packages/_plotly_utils/basevalidators.py:2694, in BaseDataValidator.validate_coerce(self, v, skip_invalid, _validate)
   2691             invalid_els.append(v_el)
   2693 if invalid_els:
-> 2694     self.raise_invalid_elements(invalid_els)
   2696 v = to_scalar_or_list(res)
   2698 # Set new UIDs

File ~/miniforge3/envs/capstone/lib/python3.10/site-packages/_plotly_utils/basevalidators.py:305, in BaseValidator.raise_invalid_elements(self, invalid_els)
    303     def raise_invalid_elements(self, invalid_els):
    304         if invalid_els:
--> 305             raise ValueError(
    306                 """
    307     Invalid element(s) received for the '{name}' property of {pname}
    308         Invalid elements include: {invalid}
    309 
    310 {valid_clr_desc}""".format(
    311                     name=self.plotly_name,
    312                     pname=self.parent_name,
    313                     invalid=invalid_els[:10],
    314                     valid_clr_desc=self.description(),
    315                 )
    316             )

ValueError: 
    Invalid element(s) received for the 'data' property of 
        Invalid elements include: [Figure({
    'data': [{'hovertemplate': 'upload_date=%{x}<br>like_count=%{y}<extra></extra>',
              'legendgroup': '',
              'line': {'color': '#636efa', 'dash': 'solid'},
              'marker': {'symbol': 'circle'},
              'mode': 'lines',
              'name': '',
              'orientation': 'v',
              'showlegend': False,
              'type': 'scatter',
              'x': array([datetime.datetime(2005, 12, 31, 0, 0),
                          datetime.datetime(2005, 12, 31, 0, 0),
                          datetime.datetime(2005, 12, 31, 0, 0), ...,
                          datetime.datetime(2019, 12, 31, 0, 0),
                          datetime.datetime(2019, 12, 31, 0, 0),
                          datetime.datetime(2019, 12, 31, 0, 0)], dtype=object),
              'xaxis': 'x',
              'y': array([374.        , 138.        , 663.16666667, ...,  19.        ,
                          754.03370787, 241.55421687]),
              'yaxis': 'y'}],
    'layout': {'legend': {'tracegroupgap': 0},
               'margin': {'t': 60},
               'template': '...',
               'xaxis': {'anchor': 'y', 'domain': [0.0, 1.0], 'title': {'text': 'upload_date'}},
               'yaxis': {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': 'like_count'}}}
})]

    The 'data' property is a tuple of trace instances
    that may be specified as:
      - A list or tuple of trace instances
        (e.g. [Scatter(...), Bar(...)])
      - A single trace instance
        (e.g. Scatter(...), Bar(...), etc.)
      - A list or tuple of dicts of string/value properties where:
        - The 'type' property specifies the trace type
            One of: ['bar', 'barpolar', 'box', 'candlestick',
                     'carpet', 'choropleth', 'choroplethmapbox',
                     'cone', 'contour', 'contourcarpet',
                     'densitymapbox', 'funnel', 'funnelarea',
                     'heatmap', 'heatmapgl', 'histogram',
                     'histogram2d', 'histogram2dcontour', 'icicle',
                     'image', 'indicator', 'isosurface', 'mesh3d',
                     'ohlc', 'parcats', 'parcoords', 'pie',
                     'pointcloud', 'sankey', 'scatter',
                     'scatter3d', 'scattercarpet', 'scattergeo',
                     'scattergl', 'scattermapbox', 'scatterpolar',
                     'scatterpolargl', 'scattersmith',
                     'scatterternary', 'splom', 'streamtube',
                     'sunburst', 'surface', 'table', 'treemap',
                     'violin', 'volume', 'waterfall']

        - All remaining properties are passed to the constructor of
          the specified trace type

        (e.g. [{'type': 'scatter', ...}, {'type': 'bar, ...}])

I am not sure what I am doing wrong. I followed these links but they did not help

  1. How To Create Subplots Using Plotly Express
  2. how can i create subplots with plotly express?
  3. Plotly: Plot multiple figures as subplots
Sashaank
  • 880
  • 2
  • 20
  • 54

1 Answers1

1

My understanding is that you can't subplot because of the facet feature in plotly.express. So it is possible to use the data obtained from px.line and specify it to the graph_object. Or you can deal with it by creating it in a graph_object from the beginning. I didn't have sample data, so I used this from an example in the official reference.

import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

df = px.data.stocks()

fig = make_subplots(rows=2, cols=1)
trace1 = px.line(df, x='date', y="GOOG")
trace2 = px.line(df, x='date', y="AAPL")

fig.add_trace(go.Scatter(mode='lines', x=trace1.data[0]['x'], y=trace1.data[0]['y']), row=1, col=1)
fig.add_trace(go.Scatter(mode='lines', x=trace2.data[0]['x'], y=trace2.data[0]['y']), row=2, col=1)
fig.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32