I am trying to create a figure using matplotlib that contains 12 plots in total. The plots are distributed as follows: There are 3 columns, and 4 rows. I want the first two rows to be "sticking" together along the y axis/vertically, i.e. there shall be no axis labels, and no figure title of the lower row in between them. The same goes for rows 3 and 4. However, I want some space between the two "row-groups" So basically rows 1 and 2 stick together, and row 3 and 4 stick together, but some space between row 2 and 3.
I was only able to find parameters that influence all heigh space between subplots, but none that let me modify the height space individually. In this MWE, I'm using the "figure.subplot.hspace"
rcParam
to modify the hspace.
#!/usr/bin/env python3
import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np
params = {
"xtick.labelsize": 12,
"ytick.labelsize": 12,
"xtick.direction": "in",
"ytick.direction": "in",
"xtick.top": True,
"ytick.right": True,
"figure.subplot.left": 0.045,
"figure.subplot.right": 0.99,
"figure.subplot.bottom": 0.05,
"figure.subplot.top": 0.93,
"figure.subplot.wspace": 0.15,
"figure.subplot.hspace": 0.0,
}
mpl.rcParams.update(params)
if __name__ == "__main__":
# invent some data
x = np.linspace(0, 2*np.pi, 100)
y_main = np.sin(x)
y_diff = 1. - y_main
fig = plt.figure(figsize=(18, 22))
ax1 = fig.add_subplot(4,3,1,)
ax2 = fig.add_subplot(4,3,2,)
ax3 = fig.add_subplot(4,3,3,)
ax1_sub = fig.add_subplot(4,3,4)
ax2_sub = fig.add_subplot(4,3,5)
ax3_sub = fig.add_subplot(4,3,6)
ax4 = fig.add_subplot(4,3,7,)
ax5 = fig.add_subplot(4,3,8,)
ax6 = fig.add_subplot(4,3,9,)
ax4_sub = fig.add_subplot(4,3,10)
ax5_sub = fig.add_subplot(4,3,11)
ax6_sub = fig.add_subplot(4,3,12)
subaxes = [ax1_sub, ax2_sub, ax3_sub, ax4_sub, ax5_sub, ax6_sub]
mainaxes = [ax1, ax2, ax3, ax4, ax5, ax6]
for ax in mainaxes:
ax.set_title("Title")
ax.plot(x, y_main)
ax.set_ylabel("y(x)")
ax.tick_params(labelbottom=False)
for ax in subaxes:
ax.plot(x, y_diff)
ax.set_xlabel("xlabel")
ax.set_ylabel("1 - y(x)")
# plt.tight_layout()
plt.savefig("mwe.png", dpi=200)
plt.close()
The resulting figure is as follows:
This is exactly how I want rows 1&2 and 3&4 to "stick together". But as you can see, the axis labels and figure titles are now missing and inside other figures, respectively.
How can I add some space between two specific rows only?
CodePudding user response:
For such 'special' plot arrangements I like to use
Code:
import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np
params = {
"xtick.labelsize": 12,
"ytick.labelsize": 12,
"xtick.direction": "in",
"ytick.direction": "in",
"xtick.top": True,
"ytick.right": True,
"figure.subplot.left": 0.045,
"figure.subplot.right": 0.99,
"figure.subplot.bottom": 0.05,
"figure.subplot.top": 0.93,
"figure.subplot.wspace": 0.15,
# "figure.subplot.hspace": 0.0, # done within gridspec
}
mpl.rcParams.update(params)
# invent some data
x = np.linspace(0, 2*np.pi, 100)
y_main = np.sin(x)
y_diff = 1. - y_main
fig = plt.figure(figsize=(18, 22), facecolor=(1, 1, 1))
gs = fig.add_gridspec(2, 1, hspace=0.15) # spacing between the two groups
# print(gs)
gs0 = gs[0].subgridspec(2, 3, hspace=0, wspace=0.2) # spacing within the groups
gs1 = gs[1].subgridspec(2, 3, hspace=0, wspace=0.2)
# print(gs0)
set1, set1_sub = gs0.subplots()
# print(set1)
set1[0].text(0.5, 0.5, "set1[0]")
set1[1].text(0.5, 0.5, "set1[1]")
set1[2].text(0.5, 0.5, "set1[2]")
set1_sub[0].text(0.5, 0.5, "set1_sub[0]")
set1_sub[1].text(0.5, 0.5, "set1_sub[1]")
set1_sub[2].text(0.5, 0.5, "set1_sub[2]")
set2 = gs1.subplots()
# print(set2)
set2[0,0].text(0.5, 0.5, "set2[0]")
set2[0,1].text(0.5, 0.5, "set2[1]")
set2[0,2].text(0.5, 0.5, "set2[2]")
set2[1,0].text(0.5, 0.5, "set2_sub[0]")
set2[1,1].text(0.5, 0.5, "set2_sub[1]")
set2[1,2].text(0.5, 0.5, "set2_sub[2]")
mainaxes = [set1[0], set1[1], set1[2], set2[0,0], set2[0,1], set2[0,2]]
subaxes = [set1_sub[0], set1_sub[1], set1_sub[2], set2[1,0], set2[1,1], set2[1,2]]
for ax in mainaxes:
ax.set_title("Title")
ax.plot(x, y_main)
ax.set_ylabel("y(x)")
ax.tick_params(labelbottom=False)
for ax in subaxes:
ax.plot(x, y_diff)
ax.set_xlabel("xlabel")
ax.set_ylabel("1 - y(x)")
#plt.savefig("mwe.png", dpi=200)
plt.show()
Notes:
- The
.text
are included as a help to identify the positions, just remove them when you've got the overview. - set1/2 (groups) are build slightly different to show how gridspec works
- both ways have the same result
- activate the
# print
statements for further insight
fig.add_gridspec(2, 1)
'main' grid with 2 rows and 1 columngs[0].subgridspec(2, 3)
subgrid within the 1st main row, with 2 rows and 3 columns