Sashaank
Sashaank

Reputation: 964

How to create subplots in plotly express

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

Upvotes: 1

Views: 3341

Answers (1)

r-beginners
r-beginners

Reputation: 35115

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

Upvotes: 1

Related Questions