How to align text with ylabel in matplotlib?

Viewed 27

I want to add a text "a)", "b)" and "c)" in subfigures and align it with the yaxis label.

Lets say we have a simple plot, with variable y-axis tick labels "0.8", "0.08", "0.016". This would increase the distance between ax[i].transAxes=0 and ylabel.

import matplotlib.pyplot as plt
import numpy as np
x=np.arange(0,1,0.01)
y=np.sin(x)


fig,ax=plt.subplots(1,3,figsize=(6,4))
ax[0].plot(x,y)
ax[1].plot(x,y*0.1)
ax[2].plot(x,y*0.02)
for i in range(3):
    ax[i].spines['top'].set_visible(False)
    ax[i].spines['right'].set_visible(False)
    ax[i].set_ylabel('Sine')
    ax[i].set_xlabel('x')
plt.tight_layout()
abc='abc'
for i in range(3):
    ax[i].text(0,1,abc[i]+')',transform=ax[i].transAxes)
plt.show()

Currently I am trying to find the (x,y) position by trial and error to right align "a)", "b)" or "c)" with the ylabel. Is there a better way to do this?

If I try to get the position of ylabel using,

ylbl=ax[i].set_ylabel('Sine')
print(ylbl.get_position())

I get (0,0.5), which is not really helpful.

More bizzare is when I do a tight_layout.

ylbls=[]
for i in range(3):
    ylbls.append(ax[i].set_ylable('Sine'))

plt.tight_layout()
for i in range(3):
    print(ylbls[i].get_position()

I get values (37.7,0.5), (201.8,0.5), (365.9,0.5). I have no idea what these 37.7, 201.8, 365.9 imply and if I can use them to align ylabel with my text somehow?

1 Answers

First, get the y-label text box information, and then use the blend transform method, x is from y-label box info, y is from ax[i].transAxes.

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.transforms import IdentityTransform
import matplotlib.transforms as transforms

x=np.arange(0,1,0.01)
y=np.sin(x)

fig,ax=plt.subplots(1,3,figsize=(7,5))
ax[0].plot(x,y)
ax[1].plot(x,y*0.1)
ax[2].plot(x,y*0.02)
for i in range(3):
    ax[i].spines['top'].set_visible(False)
    ax[i].spines['right'].set_visible(False)
    ax[i].set_ylabel('Sine')
    ax[i].set_xlabel('x')

plt.tight_layout()
fig.canvas.draw()


abc = r'abc'
for i in range(3):
    iax = ax[i]
    trans = transforms.blended_transform_factory(IdentityTransform(), iax.transAxes)
    bb = iax.yaxis.label.get_window_extent()
    iax.text(bb.x0-3,1.01,abc[i]+')',ha='left',fontsize=14,transform=trans)
  
plt.savefig('output_text.png',dpi=300)

enter image description here

Related