domiziano
domiziano

Reputation: 470

Is it possible to create a subplot with Plotly Express?

I would like to create a subplot with 2 plot generated with the function plotly.express.line, is it possible? Given the 2 plot:

fig1 =px.line(df, x=df.index, y='average')
fig1.show()

fig2 = px.line(df, x=df.index, y='Volume')
fig2.show()

I would like to generate an unique plot formed by 2 subplot (in the example fig1 and fig2)

Upvotes: 5

Views: 12832

Answers (3)

vestland
vestland

Reputation: 61104

Yes, you can build subplots using plotly express. Either

1. directly through the arguments facet_row and facet_colums (in which case we often talk about facet plots, but they're the same thing), or

2. indirectly through "stealing" elements from figures built with plotly express and using them in a standard make_subplots() setup with fig.add_traces()


Method 1: Facet and Trellis Plots in Python

Although plotly.express supports data of both wide and long format, I often prefer building facet plots from the latter. If you have a dataset such as this:

    Date variable  value
0  2019-11-04  average      4
1  2019-11-04  average      2
.
.
8  2019-12-30   volume      5
9  2019-12-30   volume      2

then you can build your subplots through:

fig = px.line(df, x='Date', y = 'value', facet_row = 'variable')

Plot 1:

enter image description here

By default, px.line() will apply the same color to both lines, but you can easily handle that through:

fig.update_traces(line_color)

This complete snippet shows you how:

import plotly.graph_objects as go
import plotly.express as px
import pandas as pd

df = pd.DataFrame({'Date': ['2019-11-04', '2019-11-04', '2019-11-18', '2019-11-18', '2019-12-16', '2019-12-16', '2019-12-30', '2019-12-30'],
                  'variable':['average', 'volume', 'average', 'volume', 'average','volume','average','volume'],
                  'value': [4,2,6,5,6,7,5,2]})

fig = px.line(df, x='Date', y = 'value', facet_row = 'variable')

fig.update_traces(line_color = 'red', row = 2)

fig.show()

Method 2: make_subplots

Since plotly express can do some pretty amazing stuff with fairly complicated datasets, I see no reason why you should not stumple upon cases where you would like to use elements of a plotly express figure as a source for a subplot. And that is very possible.

Below is an example where I've built to plotly express figures using px.line on the px.data.stocks() dataset. Then I go on to extract some elements of interest using add_trace and go.Scatter in a For Loop to build a subplot setup. You could certainly argue that you could just as easily do this directly on the data source. But then again, as initially stated, plotly express can be an excellent data handler in itself.

Plot 2: Subplots using plotly express figures as source:

enter image description here

Complete code:

import plotly.graph_objects as go
import plotly.express as px
import pandas as pd

from plotly.subplots import make_subplots

df = px.data.stocks().set_index('date')

fig1 = px.line(df[['GOOG', 'AAPL']])
fig2 = px.line(df[['AMZN', 'MSFT']])

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

for d in fig1.data:
    fig.add_trace((go.Scatter(x=d['x'], y=d['y'], name = d['name'])), row=1, col=1)
        
for d in fig2.data:
    fig.add_trace((go.Scatter(x=d['x'], y=d['y'],  name = d['name'])), row=2, col=1)
    
fig.show()

Upvotes: 8

Archer
Archer

Reputation: 41

There is no need to use graph_objects module if you have just already generated px figures for making subplots. Here is the full code.

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

df = px.data.stocks().set_index('date')

fig1 = px.line(df[['GOOG', 'AAPL']])
fig2 = px.line(df[['AMZN', 'MSFT']])

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

fig.add_trace(fig1['data'][0], row=1, col=1)
fig.add_trace(fig1['data'][1], row=1, col=1)
fig.add_trace(fig2['data'][0], row=2, col=1)
fig.add_trace(fig2['data'][1], row=2, col=1)
    
fig.show()

Plotted Figure

If there are more than two variables in each plot, one can use for loop also to add the traces using fig.add_trace method.

Upvotes: 4

Derek O
Derek O

Reputation: 19545

From the documentation, Plotly express does not support arbitrary subplot capabilities. You can instead use graph objects and traces (note that go.Scatter is equivalent):

import pandas as pd

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

## create some random data
df = pd.DataFrame(
    data={'average':[1,2,3], 'Volume':[7,3,6]}, 
    index=['a','b','c']
)

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

fig.add_trace(
    go.Scatter(x=df.index, y=df.average, name='average'),
    row=1, col=1
)

fig.add_trace(
    go.Scatter(x=df.index, y=df.Volume, name='Volume'),
    row=1, col=2
)

fig.show()

enter image description here

Upvotes: 2

Related Questions