How To Create Subplots Using Plotly Express

Question:

If you’re like me, you love Plotly Express, but were frustrated when you ran into the issue that figures returned by Express can’t utilize ‘make_subplots()’ since make_subplots takes in traces and not figures. With this post, I’d like to share my own solution on how I created a subplot containing two different types of figures (like below) using only Plotly Express (and plotly.subplots)

enter image description here

Asked By: mmarion

||

Answers:

Solution:

import plotly.express as px
import plotly.subplots as sp
import dash_core_components as dcc

# Create figures in Express
figure1 = px.line(my_df)
figure2 = px.bar(my_df)

# For as many traces that exist per Express figure, get the traces from each plot and store them in an array.
# This is essentially breaking down the Express fig into it's traces
figure1_traces = []
figure2_traces = []
for trace in range(len(figure1["data"])):
    figure1_traces.append(figure1["data"][trace])
for trace in range(len(figure2["data"])):
    figure2_traces.append(figure2["data"][trace])

#Create a 1x2 subplot
this_figure = sp.make_subplots(rows=1, cols=2) 

# Get the Express fig broken down as traces and add the traces to the proper plot within in the subplot
for traces in figure1_traces:
    this_figure.append_trace(traces, row=1, col=1)
for traces in figure2_traces:
    this_figure.append_trace(traces, row=1, col=2)

#the subplot as shown in the above image
final_graph = dcc.Graph(figure=this_figure)

I couldn’t share an actual image of my program’s output due to the sensitivity of the data of the project I’m working on, but it looks exactly like the one in the above image. As far as I’ve tested this should work with any Express figure.

I hope this can be of use to some. Happy plotting everyone!

Answered By: mmarion

The accepted answer is great, and I would like to mention a small modification addressing the first comment of it, which is only to show legends of some specific subplots. I find this modification really useful when all subplots share the very same legends and it seems redundant to let a single legend repeat multiple times.

Here is the trick. Each trace of a figure has its own 'showlegend' attribute (set to True by default for Plotly Express figures), so you may simply set this to False with an iteration, as I did for figure 2.

# I largely keep the codes and comments the same as the original answer, with the modification highlighted under '#######'
import plotly.express as px
import plotly.subplots as sp

my_df = px.data.medals_long()

# Create figures in Express
figure1 = px.bar(my_df, x = "nation", y = "count", color = "medal")
figure2 = px.line(my_df, x = "nation", y = "count", color = "medal")

# For as many traces that exist per Express figure, get the traces from each plot and store them in an array.
# This is essentially breaking down the Express fig into its traces
figure1_traces = []
figure2_traces = []
for trace in range(len(figure1["data"])):
    figure1_traces.append(figure1["data"][trace])
for trace in range(len(figure2["data"])):
    ############ The major modification. Manually set 'showlegend' attribute to False. ############
    figure2["data"][trace]['showlegend'] = False             
    figure2_traces.append(figure2["data"][trace])
    
# Create a 1x2 subplot
this_figure = sp.make_subplots(rows = 1, cols = 2, subplot_titles = ['Bar', 'Line'])
this_figure.update_layout(height = 500, width = 1200, title_text = "Medals count by country", title_font_size = 25)

# Get the Express fig broken down as traces and add the traces to the proper plot within the subplot
for traces in figure1_traces:
    this_figure.append_trace(traces, row = 1, col = 1)
for traces in figure2_traces:
    this_figure.append_trace(traces, row = 1, col = 2)
    
this_figure.show()

enter image description here

Without this modification, the legends will show twice for each group, but they can still only be displayed/hidden simultaneously.

enter image description here

Answered By: Meneshail