python - 如何使用带有多个子图的 matplotlib 吸引人地排列标题和轴标签等图形和文本?
问题描述
我想创建测量系统三轴的前后图。这接近我想要的。然而:
- 如何让“之前”和“之后”标题分别跨越子图 1+2 和 4+5?(标签不按预期工作)
- 就像“之前”和“之后”应该在列上方一样,我希望在图表行的前面有“x 轴”、“y 轴”等。我怎么做?
- 如何将子图 1+2 和 4+5 连接在一起,以便它们接触?wspace=.0 没有按预期工作。
- 如何减小中间的宽度,即 subplot 3 所在的位置,以便其他边可以占用更多空间?
- 如何在 fig.suptitle 和图形之间添加一些 hspace?
- 如何让我的代码更优雅?有很多重复。
from matplotlib.pyplot import figure
def plot_before_and_after(data_before, data_after, title):
shape = data_before.shape
sensor_num = shape[0]
n_start = 20 # number picked at random
N = 2 ** 12 # power of two is good
n_stop = n_start + N
p_stop = n_start + 40 # one periode @50Hz at the sampling rate
x_long = range(n_start, n_stop)
x_short = range(n_start, p_stop)
cmap = plt.get_cmap('jet_r')
axis_list = ['x', 'y', 'z']
fig = figure(num=None, figsize=(10, 10), dpi=80, facecolor='w', edgecolor='k')
fig.suptitle(title + "\nbefore \t\t\t\t\tafter")
plots = []
for axis_cnt in range(0, 3):
ax0 = plt.subplot(3, 5, axis_cnt * 5 + 1,
title="before, {}-Axis".format(axis_list[axis_cnt]))
for sensor_cnt in range(0, sensor_num):
color = cmap(float(sensor_cnt) / sensor_num)
plt.plot(x_long, data_before[sensor_cnt, n_start:n_stop, axis_cnt], color=color,
label="sensor" + str(sensor_cnt))
ax1 = plt.subplot(3, 5, axis_cnt * 5 + 2,
title="before, {}-Axis".format(axis_list[axis_cnt]),
sharey=ax0)
for sensor_cnt in range(0, sensor_num):
color = cmap(float(sensor_cnt) / sensor_num)
plt.plot(x_short, data_before[sensor_cnt, n_start:p_stop, axis_cnt], color=color,
label="sensor" + str(sensor_cnt))
plt.setp(ax1.get_yticklabels(), visible=False)
ax3 = plt.subplot(3, 5, axis_cnt * 5 + 4,
title="after, {}-Axis".format(axis_list[axis_cnt]))
for sensor_cnt in range(0, sensor_num):
color = cmap(float(sensor_cnt) / sensor_num)
plt.plot(x_long, data_after[sensor_cnt, n_start:n_stop, axis_cnt], color=color,
label="sensor" + str(sensor_cnt))
ax4 = plt.subplot(3, 5, axis_cnt * 5 + 5,
title="after, {}-Axis".format(axis_list[axis_cnt]),sharey=ax3)
for sensor_cnt in range(0, sensor_num):
color = cmap(float(sensor_cnt) / sensor_num)
plt.plot(x_short, data_after[sensor_cnt, n_start:p_stop, axis_cnt], color=color,
label="sensor" + str(sensor_cnt))
plt.setp(ax4.get_yticklabels(), visible=False)
plt.subplots_adjust(wspace=.0)
plt.legend()
plt.show()
解决方案
这是一个可能对您有所帮助的初步答案。我使用了 Matplotlib 的 GridSpec(有关有用信息,请参阅此处add_subplot
)和方法,在这些情况下,这两种方法似乎都很方便。gridspec 允许我们创建两组独立格式化的子图;生成各个add_subplot
轴。
代码
import matplotlib.pyplot as plt
nrow, ncol = 3, 2 # Number of rows and cols of gridspecs
lborder = [0.1, 0.6] # Left border coordinates of gridspecs
rborder = [0.45, 0.95] # Right border coordinates of gridspecs
tborder = 0.92 # Top border coordinate of gridspecs
gtitles = ['Before', 'After']
txt_axis = ['X-axis', 'Y-axis', 'Z-axis']
fig = plt.figure(figsize=(10, 10), dpi=80, facecolor='w', edgecolor='k')
for i in range(2):
gs = fig.add_gridspec(nrows=nrow, ncols=ncol, left=lborder[i],
right=rborder[i], top=tborder, hspace=0.45, wspace=0)
for j in range(nrow):
ax0 = fig.add_subplot(gs[j,0])
ax0.plot([1,2,3])
plt.text(-0.4, 0.5, txt_axis[j],
horizontalalignment='center',verticalalignment='center',
transform = ax0.transAxes, fontsize = 12)
if j == 0:
fig.text(1, 1.1, gtitles[i], fontsize=12, horizontalalignment =
'center', transform = ax0.transAxes)
for k in range(1, ncol):
ax1 = fig.add_subplot(gs[j,k], sharey = ax0)
plt.setp(ax1.get_yticklabels(), visible=False)
ax1.plot([1,2,3])
fig.suptitle('Figure title', fontsize = 14)
至于你的问题:
text
我根据这个答案创建了“之前”和“之后”标题)。- “-axis”文本也是如此。请注意,它可能会与您在垂直轴上书写的任何轴标签重叠。另请注意,现在我们必须将左侧的 gridspec 稍微向右移动(通过 的
left
参数add_gridspec
)。 wspace
也可以引入add_gridspec
。我不知道为什么它在您的代码中不起作用。- 对于 2 个网格规范之间的空间,请使用函数中的
left
和right
参数add_gridspec
。 top
主标题和子图之间的空间可以通过add_gridspec
.- 您的内部循环看起来非常相似,也许您可以定义一个函数并保存一些代码行。就我而言,我试图将所有内容都封装在一个循环中。
希望能帮助到你。
推荐阅读
- php - 如何检查用户是否存在pricing_plan_id?
- node.js - PM2 崩溃后自动重启
- javascript - 根据它的旋转将 div 从卡扇向外移动?
- chatbase - Chatbase 返回 200,但概览为空
- javascript - 按钮点击,一切都消失了
- qt - Qt:用另一个模型扩展 QFileSystemModel
- java - 放心:发布请求返回错误“JSON 输入文本不应为空或空”。
- html - 圆形进度条中的圆形图像 [CANVAS]
- ios - Firebase 不会报告 iOS 中的所有崩溃,而 Xcode 10 会报告所有崩溃,我们能否以某种方式跟踪 firebase 上的所有这些崩溃?
- android - Android RTL:阿拉伯语和希伯来语语言支持之间的差异