Reputation: 964
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
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
Upvotes: 1
Views: 3341
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()
Upvotes: 1