How To Create Subplots Using Plotly Express [duplicate]
Asked Answered
A

2

5

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

Altarpiece answered 27/4, 2021 at 21:54 Comment(3)
so express is pretty much for single plots it seems. once you have complexity, the express train derails?Greenness
@Greenness On the contrary! Complex datasets is just another area where Plotly Express shines! The solutions provided in this post will work, and you have other options as described here.Araldo
@Araldo thanks the solution at the linked post seems very good!Greenness
A
12

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!

Altarpiece answered 27/4, 2021 at 21:54 Comment(4)
Is it possible to show the legend of just one graph?. What changes should I make? (Just show trace0 not trace1)Lynd
Hi, thank you for your answer, it works. However, when i tried it for subplots of pie charts i got an error: ValueError: Trace type 'pie' is not compatible with subplot type 'xy' at grid position (1, 1). Can you advise smth, please? Thank you!Saturnalia
I suggest you to add the dcc import as wellUncharted
import dash_core_components as dccBarrow
M
3

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

Morey answered 20/9, 2022 at 8:55 Comment(1)
nice addition @Meneshail!Altarpiece

© 2022 - 2024 — McMap. All rights reserved.