如何为多个子图绘制两个交替的 x 尺度和两个交替的 y 尺度?
How to subplot two alternate x scales and two alternate y scales for more than one subplot?
我正在尝试制作一个 2x2
子图,每个内部子图由两个 x
轴和两个 y
轴组成;第一个 xy
对应于线性刻度,第二个 xy
对应于对数刻度。在假设之前有人问过这个问题之前,matplotlib 文档和 examples show how to do multiple scales for either x
or y
but not both. 是最接近我的问题的东西,我试图用这个想法来实现我想要的。我的尝试如下。
首先,我们初始化数据、刻度和刻度标签。这个想法是,替代缩放将具有相同的刻度位置和改变的刻度标签以反映替代缩放。
import numpy as np
import matplotlib.pyplot as plt
# xy data (global)
X = np.linspace(5, 13, 9, dtype=int)
Y = np.linspace(7, 12, 9)
# xy ticks for linear scale (global)
dtick = dict(X=X, Y=np.linspace(7, 12, 6, dtype=int))
# xy ticklabels for linear and logarithmic scales (global)
init_xt = 2**dtick['X']
dticklabel = dict(X1=dtick['X'], Y1=dtick['Y']) # linear scale
dticklabel['X2'] = ['{}'.format(init_xt[idx]) if idx % 2 == 0 else '' for idx in range(len(init_xt))] # log_2 scale
dticklabel['Y2'] = 2**dticklabel['Y1'] # log_2 scale
借用链接的 SO post,我将在 4 个子图中绘制相同的内容。由于每个子图中的两种缩放都使用了类似的方法,因此该方法被放入 for 循环中。但是我们需要每个的行号、列号和图号。
# 2x2 subplot
# fig.add_subplot(row, col, pnum); corresponding iterables = (irows, icols, iplts)
irows = (1, 1, 2, 2)
icols = (1, 2, 1, 2)
iplts = (1, 2, 1, 2)
ncolors = ('red', 'blue', 'green', 'black')
将所有这些放在一起,输出绘图的函数如下:
def initialize_figure(irows, icols, iplts, ncolors, figsize=None):
""" """
fig = plt.figure(figsize=figsize)
for row, col, pnum, color in zip(irows, icols, iplts, ncolors):
ax1 = fig.add_subplot(row, col, pnum) # linear scale
ax2 = fig.add_subplot(row, col, pnum, frame_on=False) # logarithmic scale ticklabels
ax1.plot(X, Y, '-', color=color)
# ticks in same positions
for ax in (ax1, ax2):
ax.set_xticks(dtick['X'])
ax.set_yticks(dtick['Y'])
# remove xaxis xtick_labels and labels from top row
if row == 1:
ax1.set_xticklabels([])
ax2.set_xticklabels(dticklabel['X2'])
ax1.set_xlabel('')
ax2.set_xlabel('X2', color='gray')
# initialize xaxis xtick_labels and labels for bottom row
else:
ax1.set_xticklabels(dticklabel['X1'])
ax2.set_xticklabels([])
ax1.set_xlabel('X1', color='black')
ax2.set_xlabel('')
# linear scale on left
if col == 1:
ax1.set_yticklabels(dticklabel['Y1'])
ax1.set_ylabel('Y1', color='black')
ax2.set_yticklabels([])
ax2.set_ylabel('')
# logarithmic scale on right
else:
ax1.set_yticklabels([])
ax1.set_ylabel('')
ax2.set_yticklabels(dticklabel['Y2'])
ax2.set_ylabel('Y2', color='black')
ax1.tick_params(axis='x', colors='black')
ax1.tick_params(axis='y', colors='black')
ax2.tick_params(axis='x', colors='gray')
ax2.tick_params(axis='y', colors='gray')
ax1.xaxis.tick_bottom()
ax1.yaxis.tick_left()
ax1.xaxis.set_label_position('top')
ax1.yaxis.set_label_position('right')
ax2.xaxis.tick_top()
ax2.yaxis.tick_right()
ax2.xaxis.set_label_position('top')
ax2.yaxis.set_label_position('right')
for ax in (ax1, ax2):
ax.set_xlim([4, 14])
ax.set_ylim([6, 13])
fig.tight_layout()
plt.show()
plt.close(fig)
调用initialize_figure(irows, icols, iplts, ncolors)
产生下图。
我正在应用相同的 xlim
和 ylim
所以我不明白为什么子图的大小都不同。此外,轴标签和轴刻度标签不在指定位置(因为 fig.add_subplot(...)
索引从 1
而不是 0
开始。
我的错误是什么,我怎样才能达到预期的结果?
(如果不清楚,我尝试将 xticklabels
和 xlabels
用于底行的线性刻度, xticklabels
和 xlabels
为顶行的对数刻度, 'yticklabelsand
ylabelsfor the linear scale on the left side of the left column, and the 'yticklabels
和 ylabels
为右列右侧的对数刻度。 color='black'
kwarg 对应于线性刻度,color='gray'
kwarg 对应于对数刻度。)
代码中的irows
和icols
列表没有任何作用。要在 2x2 网格中创建 4 个子图,您将遍历 range(1,5)
、
for pnum in range(1,5):
ax1 = fig.add_subplot(2, 2, pnum)
这可能不是代码中的唯一问题,但只要未正确创建子图,就不值得进一步查看。
我正在尝试制作一个 2x2
子图,每个内部子图由两个 x
轴和两个 y
轴组成;第一个 xy
对应于线性刻度,第二个 xy
对应于对数刻度。在假设之前有人问过这个问题之前,matplotlib 文档和 examples show how to do multiple scales for either x
or y
but not both.
首先,我们初始化数据、刻度和刻度标签。这个想法是,替代缩放将具有相同的刻度位置和改变的刻度标签以反映替代缩放。
import numpy as np
import matplotlib.pyplot as plt
# xy data (global)
X = np.linspace(5, 13, 9, dtype=int)
Y = np.linspace(7, 12, 9)
# xy ticks for linear scale (global)
dtick = dict(X=X, Y=np.linspace(7, 12, 6, dtype=int))
# xy ticklabels for linear and logarithmic scales (global)
init_xt = 2**dtick['X']
dticklabel = dict(X1=dtick['X'], Y1=dtick['Y']) # linear scale
dticklabel['X2'] = ['{}'.format(init_xt[idx]) if idx % 2 == 0 else '' for idx in range(len(init_xt))] # log_2 scale
dticklabel['Y2'] = 2**dticklabel['Y1'] # log_2 scale
借用链接的 SO post,我将在 4 个子图中绘制相同的内容。由于每个子图中的两种缩放都使用了类似的方法,因此该方法被放入 for 循环中。但是我们需要每个的行号、列号和图号。
# 2x2 subplot
# fig.add_subplot(row, col, pnum); corresponding iterables = (irows, icols, iplts)
irows = (1, 1, 2, 2)
icols = (1, 2, 1, 2)
iplts = (1, 2, 1, 2)
ncolors = ('red', 'blue', 'green', 'black')
将所有这些放在一起,输出绘图的函数如下:
def initialize_figure(irows, icols, iplts, ncolors, figsize=None):
""" """
fig = plt.figure(figsize=figsize)
for row, col, pnum, color in zip(irows, icols, iplts, ncolors):
ax1 = fig.add_subplot(row, col, pnum) # linear scale
ax2 = fig.add_subplot(row, col, pnum, frame_on=False) # logarithmic scale ticklabels
ax1.plot(X, Y, '-', color=color)
# ticks in same positions
for ax in (ax1, ax2):
ax.set_xticks(dtick['X'])
ax.set_yticks(dtick['Y'])
# remove xaxis xtick_labels and labels from top row
if row == 1:
ax1.set_xticklabels([])
ax2.set_xticklabels(dticklabel['X2'])
ax1.set_xlabel('')
ax2.set_xlabel('X2', color='gray')
# initialize xaxis xtick_labels and labels for bottom row
else:
ax1.set_xticklabels(dticklabel['X1'])
ax2.set_xticklabels([])
ax1.set_xlabel('X1', color='black')
ax2.set_xlabel('')
# linear scale on left
if col == 1:
ax1.set_yticklabels(dticklabel['Y1'])
ax1.set_ylabel('Y1', color='black')
ax2.set_yticklabels([])
ax2.set_ylabel('')
# logarithmic scale on right
else:
ax1.set_yticklabels([])
ax1.set_ylabel('')
ax2.set_yticklabels(dticklabel['Y2'])
ax2.set_ylabel('Y2', color='black')
ax1.tick_params(axis='x', colors='black')
ax1.tick_params(axis='y', colors='black')
ax2.tick_params(axis='x', colors='gray')
ax2.tick_params(axis='y', colors='gray')
ax1.xaxis.tick_bottom()
ax1.yaxis.tick_left()
ax1.xaxis.set_label_position('top')
ax1.yaxis.set_label_position('right')
ax2.xaxis.tick_top()
ax2.yaxis.tick_right()
ax2.xaxis.set_label_position('top')
ax2.yaxis.set_label_position('right')
for ax in (ax1, ax2):
ax.set_xlim([4, 14])
ax.set_ylim([6, 13])
fig.tight_layout()
plt.show()
plt.close(fig)
调用initialize_figure(irows, icols, iplts, ncolors)
产生下图。
我正在应用相同的 xlim
和 ylim
所以我不明白为什么子图的大小都不同。此外,轴标签和轴刻度标签不在指定位置(因为 fig.add_subplot(...)
索引从 1
而不是 0
开始。
我的错误是什么,我怎样才能达到预期的结果?
(如果不清楚,我尝试将 xticklabels
和 xlabels
用于底行的线性刻度, xticklabels
和 xlabels
为顶行的对数刻度, 'yticklabelsand
ylabelsfor the linear scale on the left side of the left column, and the 'yticklabels
和 ylabels
为右列右侧的对数刻度。 color='black'
kwarg 对应于线性刻度,color='gray'
kwarg 对应于对数刻度。)
代码中的irows
和icols
列表没有任何作用。要在 2x2 网格中创建 4 个子图,您将遍历 range(1,5)
、
for pnum in range(1,5):
ax1 = fig.add_subplot(2, 2, pnum)
这可能不是代码中的唯一问题,但只要未正确创建子图,就不值得进一步查看。