Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subplots with two y axes (each) - plotly and python/pandas

Are there guidelines on how to set up secondary Y-axes in python for plotly? I am assinging axis style through an iterative loop, as follows:

all_plots = ['plot1','plot2'...'plot20']
fig = tools.make_subplots(rows=nrow, cols=ncol, shared_xaxes=False, shared_yaxes=False, subplot_titles=all_plots)
for i in all_plots:
    fig['layout']['yaxis'+str(j)].update()

How does the assignment of y axes work?

If my subplot included, say, 4 rows and 5 columns for a total of 20 subplots, do I have to assume that plotly needs to receive odd and even numbers, meaning: yaxis1 and yaxis2 for plot1

....

yaxis39 and yaxis40 for plot20

like image 457
Andreuccio Avatar asked Sep 17 '25 23:09

Andreuccio


1 Answers

It is possible, to do this, but its not particularly intuitive. Take this example where I create a plot 2x2 subplots, and add a secondary y axis to the plot in position 2,2.

When you create a subplots, they are assigned y axes: "y1","y2","y3","y4" on the left side of each subplot. To a secondary y axes, you need to use fig['layout'].updateto create new axes "y5", "y6", "y7", "y8" which correspond to "y1","y2","y3","y4". So the bottom right subplot would have axes y4(right) and y8(left). In the example below, I only create a secondary y axis for the last plot, but expanding it to more/all the subplots is pretty straightforward.

It is important to note, that creating the secondary axes, and assigning it in trace5 doesn't automatically place it on the proper axes. You still have to manually assign it with fig['data'][4].update(yaxis='y'+str(8)) to plot it relative to the left axis.

fig = tools.make_subplots(rows=2, cols=2,subplot_titles=('Air Temperature', 'Photon Flux Density',
                                                         'Ground Temps','Water Table & Precip'))


fig['layout']['xaxis1'].update( range=[174, 256])
fig['layout']['xaxis3'].update(title='Day of Year', range=[174, 256])
fig['layout']['yaxis1'].update(title='Degrees C',range=[-5,30])
fig['layout']['yaxis2'].update(title='mmol m<sup>-2</sup> m<sup>-d</sup>', range=[0, 35])
fig['layout']['yaxis3'].update(title='Ground Temps', range=[0, 11])
fig['layout']['yaxis4'].update(title='depth cm', range=[-20, 0])
fig['layout']['yaxis8'].update(title='rainfall cm', range=[0, 1.6])
fig['layout'].update(showlegend=False, title='Climate Conditions')



# In this example, I am only doing it for the last subplot, but if you wanted to do if for all, 
# Just change to range(1,5)

for k in range(4,5):  
    fig['layout'].update({'yaxis{}'.format(k+4): dict(anchor='x'+str(k),
                                                          overlaying='y'+str(k),
                                                          side='right',
                                                         )
                            })

trace1 = go.Scatter(
        y=Daily['AirTC_Avg'],
        x=Daily.index,
        marker = dict(
        size = 10,
        color = 'rgba(160, 0, 0, .8)',),
        error_y=dict(
            type='data',
            array=Daily_Max['AirTC_Avg']-Daily_Min['AirTC_Avg'],
            visible=True,
        color = 'rgba(100, 0, 0, .5)',
        ),
    name = 'Air Temp'
    )

trace2 = go.Bar(
        y=Daily['PPFD']/1000,
        x=Daily.index,
        name='Photon Flux',
        marker=dict(
            color='rgb(180, 180, 0)'
        ),

    yaxis='y2',
)

trace3 = go.Scatter(
        y=Daily['Temp_2_5_1'],
        x=Daily.index,
        name='Soil Temp',
        marker=dict(
            color='rgb(180, 0, 0)'
        ),

    yaxis='y3',
)


trace4 = go.Scatter(
        y=Daily['Table_1']*100,
        x=Daily.index,
        name='Water Table',
        marker=dict(
            color='rgb(0, 0, 180)'
        ),

    yaxis='y4',
)

trace5 = go.Bar(
        y=Daily['Rain']/10,
        x=Daily.index,
        name='Rain',
        marker=dict(
            color='rgb(0, 100, 180)'
        ),

    yaxis='y8',
)

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


## This part is important!!! you have to manually assing the data to the axis even 
# though you do it when defining trace 5
fig['data'][4].update(yaxis='y'+str(8))
plot(fig, filename='FI_Climate')
like image 51
June Skeeter Avatar answered Sep 20 '25 13:09

June Skeeter