Draw a separator or lines between subplots

I find a solution but not a perfect one, but works for me.

Apply below code to each object of subplot.

Where [-1, 1.5] are values suppose to cover all areas of X axis in figure. not all the same.

axes.plot([-1, 1.5], [0, 0], color='black', lw=1, transform=axes.transAxes, clip_on=False)
axes.plot([-1, 1.5], [1, 1], color='black', lw=1, transform=axes.transAxes, clip_on=False)

I tried another way which I think is the most perfect way. As the code show below.

    trans = blended_transform_factory(self.figure.transFigure, axes.transAxes)
    line = Line2D([0, 1], [0, 0], color='w', transform=trans)
    self.figure.lines.append(line)

In above code the line would begin at the start of every figure edge, and it will change when the figure size changed.


If the axes/subplots have decorators like x labels or tick labels, it's not straight forward to find the correct position of the lines that should separate the subplots, such that they do not overlap with the texts.

One solution to this can be to get the extent of the axes including decorators and take the mean in between the bottom of the upper and the top of the lower extent.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms as mtrans

fig, axes = plt.subplots(3,2, squeeze=False)

for i, ax in enumerate(axes.flat):
    ax.plot([1,2])
    ax.set_title('Title ' + str(i+1))
    ax.set_xlabel('xaxis')
    ax.set_ylabel('yaxis')

# rearange the axes for no overlap
fig.tight_layout()

# Get the bounding boxes of the axes including text decorations
r = fig.canvas.get_renderer()
get_bbox = lambda ax: ax.get_tightbbox(r).transformed(fig.transFigure.inverted())
bboxes = np.array(list(map(get_bbox, axes.flat)), mtrans.Bbox).reshape(axes.shape)

#Get the minimum and maximum extent, get the coordinate half-way between those
ymax = np.array(list(map(lambda b: b.y1, bboxes.flat))).reshape(axes.shape).max(axis=1)
ymin = np.array(list(map(lambda b: b.y0, bboxes.flat))).reshape(axes.shape).min(axis=1)
ys = np.c_[ymax[1:], ymin[:-1]].mean(axis=1)

# Draw a horizontal lines at those coordinates
for y in ys:
    line = plt.Line2D([0,1],[y,y], transform=fig.transFigure, color="black")
    fig.add_artist(line)


plt.show()

enter image description here