【问题标题】:How to subplot two alternate x scales and two alternate y scales for more than one subplot?如何为多个子图绘制两个备用 x 比例和两个备用 y 比例?
【发布时间】:2018-09-29 01:27:47
【问题描述】:

我正在尝试制作一个2x2 子图,每个内部子图由两个x 轴和两个y 轴组成;第一个xy 对应于线性刻度,第二个xy 对应于对数刻度。在假设之前已经问过这个问题之前,matplotlib 文档和 examples show how to do multiple scales for either xy 但不是两者兼而有之。 This post on stackoverflow 是最接近我的问题的东西,我试图用这个想法来实现我想要的。我的尝试如下。

首先,我们初始化数据、刻度和刻度标签。这个想法是交替缩放将具有相同的刻度位置和更改的刻度标签以反映交替缩放。

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 帖子,我将在 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)会产生下图。

我正在应用相同的xlimylim,所以我不明白为什么子图的大小都不同。此外,轴标签和轴刻度标签不在指定位置(因为fig.add_subplot(...) 索引从1 而不是0 开始。

我的错误是什么?如何才能达到预期的效果?

(如果不清楚,我试图将xticklabelsxlabels 放在最下面一行,将xticklabelsxlabels 放在最上面一行, 'yticklabelsandylabelsfor the linear scale on the left side of the left column, and the 'yticklabelsylabels 为右栏右侧的对数刻度。color='black' kwarg 对应于线性刻度,color='gray' kwarg 对应于对数刻度。 )

【问题讨论】:

  • 在没有看太多细节的情况下,在我看来,(第一个)问题是,如果您想要 4 个子图,则数字 4 至少应该在代码中的某个位置出现一次。但事实并非如此。
  • @ImportanceOfBeingErnest 我使用irows = (1, 1, 2, 2)icols = (1, 2, 1, 2)iplts = (1, 2, 1, 2) 迭代地使用fig.add_subplot(row, col, pnum)(其中rowi-th 的值irows)。更改 iplts = (1, 2, 3, 4) 会导致错误:ValueError: num must be 1 <= num <= 2, not 3。如果4不属于iplts的地块数量,应该去哪里?

标签: python-3.x matplotlib figure subplot multiple-axes


【解决方案1】:

irowsicols 列出的代码没有任何用途。要在 2x2 网格中创建 4 个子图,您需要遍历 range(1,5)

for pnum in range(1,5):
    ax1 = fig.add_subplot(2, 2, pnum)

这可能不是代码中唯一的问题,但只要子图没有正确创建,就不值得往下看。

【讨论】:

  • 这是我代码中的错误。用pnum 更正了rowcol 数字,谢谢!
  • 我也喜欢fig, axes = plt.subplots(nrows=2, ncols=2, figsize=...)的语法。这将创建一个带有四个子图的图形。 axes 只是一个带有四个轴手柄的矩阵。 @Mpath
猜你喜欢
  • 2020-10-14
  • 2020-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多