# It is difficult to plan for layout in mixed subplots

**URL:** <https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475>\
**Category:** 📊 Plotly Python\
**Created:** [March 27, 2019, 2:16pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475 "2019-03-27T14:16:58Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![ted930511](https://avatars.discourse-cdn.com/v4/letter/t/ac8455/32.png) [@ted930511](https://community.plotly.com/u/ted930511)\
**Post date:** [March 27, 2019, 2:16pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/1 "2019-03-27T14:16:58Z")

</div>

I looked a mixed subplots example in Plotly web site [here](https://plot.ly/python/mixed-subplots/)

To be honest, Plotly is really great for plot single figure with simple layout. However, when it comes to complexed mixed subplots, it is really mess when you have to make a plan on the overal layout.

In the example, it is subplots with three axes, and the nest structure of dict in the layout make me really sad. Usually I spend a lot time planning on the details of the layout.

Compared with matplotlib, it automatically generates subplots `axes` objects using subplots function or other related functions, then you can use related methods like `imshow`, `plot_surface`, `scatter` and etc to generate the figure. I’d say this is more of a python way of doing the figure. From my personal perspetive, this is more accepted in the community.

The complex nested Layout API is really the thing that make me NOT use Plolty as my main graph drawing package during my work and reseach related staff. But sometimes , I do need some 3D functionality of Plotly that matplotlib not good at.

I posted here to see if there is any other user of Plotly feel the same, and how they solve the problem.

I have four yeas of experience using matplotlib, I tried other packages like seaborn, bokeh, Plotly. In terms of API, matplotlib did a really great job. In term of 3d plot and simple layout graph, Plotly is my favorite. Discusssions are welcomed!!!

Thanks!!!

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [March 27, 2019, 9:06pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/2 "2019-03-27T21:06:53Z")

</div>

@ted930511 The example of mixed subplots at the given link doesn’t use `plotly.tools.make_subplots()` and the user has to set the domain for each axis. This is an example [https://plot.ly/~empet/15130](https://plot.ly/~empet/15130) on how to call `tools.make_subplots()`, and update the layout to meet your requirements.

---

<div class="post-metadata">

**Author:** ![ted930511](https://avatars.discourse-cdn.com/v4/letter/t/ac8455/32.png) [@ted930511](https://community.plotly.com/u/ted930511)\
**Post date:** [March 28, 2019, 1:26am UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/3 "2019-03-28T01:26:25Z")

</div>

@empet, thank you! It seems using layout.update() is the core in the example code. Anyway, this is much better than the example in the documentation example.

---

<div class="post-metadata">

**Author:** ![ted930511](https://avatars.discourse-cdn.com/v4/letter/t/ac8455/32.png) [@ted930511](https://community.plotly.com/u/ted930511)\
**Post date:** [March 28, 2019, 2:34am UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/4 "2019-03-28T02:34:14Z")

</div>

@empet, Hi, I implemented the code you provided. I really liked the way you organize the layout. One more question about using the `update()` function.

**Is there a programmable way to correlate the traces to the corresponding axes**. After appending traces to fig, I tired code below.

```
fig.append_trace(trace1, 1,1)
fig.append_trace(trace2, 1,2)
fig.append_trace(trace3, 2,1)
fig.append_trace(trace4, 2,1)

trace1.scene.update(...) # this do not work, because trace1.scene returns a None type

```

In the example code, you use:

```
fig.layout.scene.update(xaxis=axis3d,
                    yaxis=axis3d,
                    zaxis=axis3d,
                    camera=dict(eye=dict(x=1.4, y=1.4, z=1.4)))

```

xaxis refers to the 3d axis, so it will be updated. I am wondering if there is a programmable way to establish the trace to axis correspondence.

Thanks!

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [March 28, 2019, 7:53am UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/5 "2019-03-28T07:53:19Z")

</div>

Hi @ted930511,

The correspondence cell-axes is displayed after fig definition:

```auto
This is the format of your plot grid:
[(1,1) scene1] [(1,2) x1,y1] 
[ (2,1) x2,y2

```

i.e. the 3d trace should be appended to the cell(1,1), and the 2d traces to (1,2), respectively (2,1).  
The layout for each cell is described in fig.layout, not in the trace definition.

`fig.append_trace(tracename, i,j)`

assigns the trace 'tracename` to the cell (i,j) and its layout is described by xaxis, yaxis associated to that cell.

To clarify how we make updates like `fig.layout.scene.update()` or `fig.layout.scene2.update()` I defined in this notebook [https://plot.ly/~empet/15133](https://plot.ly/~empet/15133) a new subplot, with two 3d cells and two 2d cells.

Note that you can read off the scene name for the 3d case, respectively the axes name for 2d cells from the info displayed after `fig` definition:

```auto
fig = tools.make_subplots(specs=[[{'is_3d': True}, {'is_3d':True}], 
                                 [{}, {}]],
                                 
                           vertical_spacing=0.075,
                           horizontal_spacing=0.075,
                           rows=2,
                           cols=2
                         )

```

```auto
This is the format of your plot grid:
[(1,1) scene1] [(1,2) scene2]
[(2,1) x1,y1] [(2,2) x2,y2] 

```

The `scene1` for a 3d layout and `xaxis1`, `yaxis1` in a 2d layout can be accessed as `scene`,  
respectively `xaxis, yaxis`, too (i.e. the missing index is automatically understood as 1)  
(this rule can be a bit confusing).

In `scene1`, and `scene2` the axes name is not indexed because we access them via their parent, `scene`.  
The axes in cell (2, 1) are `xaxis1`, `yaxis1`, while in the cell (2,2) they are `xaxis2, yaxis2`.

---

<div class="post-metadata">

**Author:** ![jmmease](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jmmease/32/3706_2.png) [@jmmease](https://community.plotly.com/u/jmmease)\
**Post date:** [March 28, 2019, 10:47am UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/6 "2019-03-28T10:47:41Z")

</div>

Hi @ted930511,

Thanks for your feedback and thanks @empet for the good examples. I’m the maintainer of plotly.py and I totally agree that subplotting can be a pain sometimes 🙂

The `make_subplots` API helps a lot, but it currently has the limitation that it only works for 2D and 3D cartesian subplot types (not geo, parcoords, pie, parcats, etc.).

One of my big goals for version 4 is figuring out how to make subplotting smoother. An impetus for this is that in version 4 we’ll be integrating the newly released [`plotly_express`](https://www.plotly.express/) into plotly.py. plotly\_express makes it really easy to make faceted subplots, but it’s current subplot approach isn’t compatible with plotly.py’s `make_subplots` approach.

As an experienced matplotlib user, do you think an improved `make_subplots` API that covers all trace types would feel natural to you? After the initial figure is created using `make_subplots`, what other subplot operations would you want to be able to perform on the figure. For example we have methods for adding traces to particular subplots, but we don’t have anything get for retrieving traces or axis objects based on subplot.

Some related issues that you may want to weigh in on:

- [https://github.com/plotly/plotly.py/issues/1436](https://github.com/plotly/plotly.py/issues/1436)
- [https://github.com/plotly/plotly.py/issues/1482](https://github.com/plotly/plotly.py/issues/1482)

-Jon

---

<div class="post-metadata">

**Author:** ![nqv](https://avatars.discourse-cdn.com/v4/letter/n/c2a13f/32.png) [@nqv](https://community.plotly.com/u/nqv)\
**Post date:** [October 11, 2020, 12:58am UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/7 "2020-10-11T00:58:04Z")

</div>

Hi Empet,

Thanks for sharing lots of useful tips as always

I just have a follow-up question on your demonstration to plot mixed subplots for 2D and 3D figures. It works great when you only need a y axis on each subplot. However, I believe tool.make\_subplots cannot handle multiple y-axes on a subplot, correct?

So how do we create 2x1 subplots, where a 3D figure is shown on the first row, and then a subplot on 2nd row with multiple y-axes?

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [October 11, 2020, 6:11am UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/8 "2020-10-11T06:11:40Z")

</div>

Hi @nqv,

You can define mixed subplots using `make_subplots`:

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

fig = make_subplots(
    rows=2, cols=1, vertical_spacing=0.05,
    specs=[[{"type": "scene"}], [{"secondary_y": True}]])
#IMPORTANT!!!! To decide how to update the plot layout, print fig.layout to see its initial definition
print(fig.layout)
fig.add_trace(go.Scatter3d(x=[3, 2, 5, 7],
                           y=[1, 3, 4, 6],
                           z=[4, 2, 1, 6], 
                           name='scatt3d',
                           mode='lines', 
                           marker_size=2), 1, 1);

fig.add_trace(
    go.Bar(x=[1, 2, 3, 4],
           y=[7, 4, 5, 6],
           name="bar",
           visible=True
          ), 2, 1, secondary_y=False)

fig.add_trace(
    go.Scatter(x=[1, 2, 3, 4],
               y=[4, 2, 5, 3],
               name="scatt2d",
               line_color="black"
              ), 2, 1,secondary_y=True)

fig.update_layout(width=600, height=600, yaxis_domain=[0, 0.4])
fig.update_scenes(camera_eye=dict(x=1.65, y=1.65, z=0.5))

```

---

<div class="post-metadata">

**Author:** ![nqv](https://avatars.discourse-cdn.com/v4/letter/n/c2a13f/32.png) [@nqv](https://community.plotly.com/u/nqv)\
**Post date:** [October 11, 2020, 2:32pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/9 "2020-10-11T14:32:42Z")

</div>

Hi @empet,

Really appreciate your fast response.

I saw that I can specify “secondary\_y” on the make\_subplots and then enable secondary\_y (True or False) in the fig.add\_trace to add a secondary y-axis to one of the subplots. What about adding a tertiary y-axis on the right and 4th y-axis on the left? At this point, should I use the low-level API to specify yaxis, yaxis1 to yaxis4 in the fig.layout\_update as suggested by this [Plotly-Multiple-Axes](https://plotly.com/python/multiple-axes/)?

Here is my the breakdown of my approach so far:

1. Use make\_subplots to make 2x1 subplot grid where a 3D plot will be on the first row and 2D plot on secondary row.  
fig =tools.make\_subplots(specs=[[{‘is\_3d’: True}],  
[{‘secondary\_y’:True}]],

I use tools.make\_subplots here instead of make\_subplots because I want my ‘fig’ in the Figure type instead of tuple. It’s more convenient for me right now, because I don’t have to change my code a lot to make it worked with tuple.

1. Add traces to the figure per your suggestion  
fig.add\_trace(go.Scatter3d(), row=1, col=1 )  
fig.add\_trace(go.Scatter(), row=2, col=1, secondary\_y=False )  
fig.add\_trace(go.Scatter(), row=2, col=1, secondary\_y=True )  
fig.add\_trace(go.Scatter(), row=2, col=1 )  
I’m not sure what to do with the last trace. I wanted to show this trace on the secondary subplot as a tertiary y-axis on the right.

print(fig.layout) showed:  
‘xaxis’: {‘anchor’: ‘y’, ‘domain’: [0.15, 0.9], ‘title’: {‘text’: ‘Depth (ft)’}},  
‘yaxis’: {‘anchor’: ‘x’,  
‘domain’: [0.0, 0.1632352941176471],  
‘range’: [0, 14000],  
‘tickfont’: {‘color’: ‘#d62728’},  
‘title’: {‘font’: {‘color’: ‘#d62728’}, ‘text’: ‘ **Y-axis1** ’}},  
‘yaxis2’: {‘anchor’: ‘x’,  
‘linecolor’: ‘#2d6dfa’,  
‘overlaying’: ‘y’,  
‘range’: [0, 120],  
‘side’: ‘right’,  
‘tickfont’: {‘color’: ‘#2d6dfa’},  
‘title’: {‘font’: {‘color’: ‘#2d6dfa’}, ‘text’: ‘ **Y-axis2** ’}},  
‘yaxis3’: {‘anchor’: ‘free’,  
‘linecolor’: ‘#fbcb09’,  
‘overlaying’: ‘y’,  
‘position’: 0.98,  
‘range’: [0, 6],  
‘side’: ‘right’,  
‘tickfont’: {‘color’: ‘#fbcb09’},  
‘title’: {‘font’: {‘color’: ‘#fbcb09’}, ‘text’: ‘ **Y-axis3** ’}},

So, I figured I need to define the yaxis4, so i called  
fig.update\_layout(

yaxis4=dict(  
title=‘ **Y-axis4** ’,  
titlefont=dict(  
color=’#fbcb09’  
),  
tickfont=dict(  
color=’#fbcb09’  
),  
anchor=‘free’,  
overlaying=‘y’,  
side=‘right’,  
linecolor=’#fbcb09’,

```
    position=0.98,
    range=[0,6]

),

```

)  
Then I indicated xaxis=‘x’ and yaxis=‘y4’ on the add\_trace for the last trace. It didn’t work out either.

Can you give me more advice, please?

Thanks

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [October 12, 2020, 8:11pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/10 "2020-10-12T20:11:20Z")

</div>

@nqv

This is an example of multiple yaxes (more than two) for subplots with 1 column and two rows:

> **[b'Example of subplots with rows=2 | empet | Plotly'](https://chart-studio.plotly.com/~empet/15657/example-of-subplots-with-rows2/)**

---

<div class="post-metadata">

**Author:** ![nqv](https://avatars.discourse-cdn.com/v4/letter/n/c2a13f/32.png) [@nqv](https://community.plotly.com/u/nqv)\
**Post date:** [October 13, 2020, 3:56pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/11 "2020-10-13T15:56:05Z")

</div>

Thanks @empet

I figured it out based on the resources that you provided to me.

I found all your example codes are extremely helpful. Do you post all your examples somewhere? So I can use them as a reference for the future?

---

<div class="post-metadata">

**Author:** ![empet](https://avatars.discourse-cdn.com/v4/letter/e/977dab/32.png) [@empet](https://community.plotly.com/u/empet)\
**Post date:** [October 13, 2020, 4:40pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/12 "2020-10-13T16:40:02Z")

</div>

@nqv Here [https://chart-studio.plotly.com/~empet#/](https://chart-studio.plotly.com/~empet#/) you can find all my plots/jupyter notebooks.

---

<div class="post-metadata">

**Author:** ![nqv](https://avatars.discourse-cdn.com/v4/letter/n/c2a13f/32.png) [@nqv](https://community.plotly.com/u/nqv)\
**Post date:** [October 13, 2020, 4:52pm UTC](https://community.plotly.com/t/it-is-difficult-to-plan-for-layout-in-mixed-subplots/21475/13 "2020-10-13T16:52:27Z")

</div>

Thanks again @empet. Appreciate your time and help.
