SHV_la
SHV_la

Reputation: 987

Is there a way to add a second y axis to a subplot?

(I think) I know about the twiny/x function in matplotlib, but I am really struggling to figure out how to use this function in a subplot context. I have a line plot like this showing rainfall data:

enter image description here

Generated by this code:

fig,ax = plt.subplots(3, figsize=(10,15),sharey=True)

ax[0].plot(YEAR1['pcp_1D_tot'], label='RG')
ax[0].plot(YEAR1['ppt_1D'], label='TRMM')
ax[0].set_title('Year 1',x=0.1,y=0.9)

ax[1].plot(YEAR2['pcp_1D_tot'], label='RG')
ax[1].plot(YEAR2['ppt_1D'], label='TRMM')
ax[1].set_title('Year 2',x=0.1,y=0.9)
ax[1].set_ylabel('Rainfall total (mm/day)')

ax[2].plot(YEAR3['pcp_1D_tot'], label='RG')
ax[2].plot(YEAR3['ppt_1D'], label='TRMM')
ax[2].set_title('Year 3',x=0.1,y=0.9)
ax[2].set_xlabel('Date')

fig.legend(loc=(0.8,0.9))
fig.tight_layout()
plt.show()

But I also have data on flood magnitude I would like to add which is in categories of 1, 2, and 3, stored in a column named, e.g.

YEAR1['Size'] 

I'd like to plot these as a scatter plot on top of the line plot to show their incidence relative to rainfall, and so I believe I need to add another y axis on the right, but I am very unclear how to do this.

Can anyone help?

**###########UPDATE############### **

Thanks to the contributions below, I managed to make the following, which is exactly what I was hoping for:

enter image description here

By using the following code:

x = YEAR1m.index #### these are referring to other data that has been filtered
y = YEAR2m.index
z = YEAR3m.index

fig,ax = plt.subplots(3, figsize=(10,15),sharey=True)

ax[0].plot(YEAR1['pcp_1D_tot'], label='RG')
ax[0].plot(YEAR1['ppt_1D'], label='TRMM')
ax[0].set_title('Year 1',x=0.1,y=0.9)
ax0 = ax[0].twinx()
ax0.scatter(x, YEAR1m['Size'], marker='*', color='r',s=100)
ax0.set_ylim([0,3.2])
ax0.set_yticklabels(['0',' ','1',' ','2',' ','3'])


ax[1].plot(YEAR2['pcp_1D_tot'], label='RG')
ax[1].plot(YEAR2['ppt_1D'], label='TRMM')
ax[1].set_title('Year 2',x=0.1,y=0.9)
ax[1].set_ylabel('Rainfall total (mm/day)')
ax1 = ax[1].twinx()
ax1.scatter(y, YEAR2m['Size'], marker='*', color='r',s=100)
ax1.set_ylim([0,3.2])
ax1.set_yticklabels(['0',' ','1',' ','2',' ','3'])



ax[2].plot(YEAR3['pcp_1D_tot'], label='RG')
ax[2].plot(YEAR3['ppt_1D'], label='TRMM')
ax[2].set_title('Year 3',x=0.1,y=0.9)
ax[2].set_xlabel('Date')
ax2 = ax[2].twinx()
ax2.scatter(z, YEAR3m['Size'], marker='*', color='r',s=100)
ax2.set_ylim([0,3.2])
ax2.set_yticklabels(['0',' ','1',' ','2',' ','3'])


# fig.legend(loc=(0.8,0.9))
fig.tight_layout()
plt.show()

Upvotes: 6

Views: 14499

Answers (2)

gboffi
gboffi

Reputation: 25023

I have not your data, let's see if I understood your problem...

Usual stuff,

import matplotlib.pyplot as plt 
import numpy as np 

Generate some data

x = np.linspace(0, 1.57, 21) 
y = np.sin(x) 
z = 4*np.random.random(21) 

Prepare the figure with two subplots — I'm going to use only the first one to avoid have you bored — add a parasitic axes not to the current plot but to a specific axes

fig, (ax0, ax1) = plt.subplots(2, 1) 
ax01 = ax0.twinx() 

Plot the curve(s), plot the scatter points using different colors (this is not dealt with automatically)

ax0.plot(x, y, color='blue') 
ax01.scatter(x, z, color='red') 

This is a bit of an unrequested final touch... (note, it's colors, not color)

ax0.tick_params(axis='y',  colors='blue') 
ax01.tick_params(axis='y', colors='red')                                         

and finally plt.show() gives us

enter image description here

I'd like to add: thank you Rutger Kassies for your fine answer, where the reader of my answer can find further advice on customizing all the details of the two vertical spines.

Upvotes: 2

Sheldore
Sheldore

Reputation: 39052

In the absence of data, I can only provide a guess solution. The following should work. You will have to use individual subplot object to create a secondary y-axis using twinx

fig,ax = plt.subplots(3, figsize=(10,15),sharey=True)

ax[0].plot(YEAR1['pcp_1D_tot'], label='RG')
ax[0].plot(YEAR1['ppt_1D'], label='TRMM')
ax[0].set_title('Year 1',x=0.1,y=0.9)

ax0 = ax[0].twinx()
ax0.plot(YEAR1['Size'])


ax[1].plot(YEAR2['pcp_1D_tot'], label='RG')
ax[1].plot(YEAR2['ppt_1D'], label='TRMM')
ax[1].set_title('Year 2',x=0.1,y=0.9)
ax[1].set_ylabel('Rainfall total (mm/day)')

ax1 = ax[1].twinx()
ax1.plot(YEAR2['Size'])

ax[2].plot(YEAR3['pcp_1D_tot'], label='RG')
ax[2].plot(YEAR3['ppt_1D'], label='TRMM')
ax[2].set_title('Year 3',x=0.1,y=0.9)
ax[2].set_xlabel('Date')

ax2 = ax[2].twinx()
ax2.plot(YEAR3['Size'])

Upvotes: 4

Related Questions