【问题标题】:Python - Add residuals to subplots generated by a for loopPython - 将残差添加到由 for 循环生成的子图中
【发布时间】:2017-11-06 19:56:05
【问题描述】:

使用add_axes 添加残差时,我无法让子图工作。它在没有残差的情况下效果很好,我可以将残差添加到一个图中。这是我正在做的一个例子:

首先,让您了解我正在绘制的内容,(t, y) 是我要绘制的数据,fit 是对数据的拟合,diff 是拟合和数据之间的差异。

t, s, fit = [], [], []
diff = []
for i in range(12):
    t.append(x / y[i])

    s.append(np.linspace(0, 1, num=100, endpoint=True))
    fit.append(UnivariateSpline(t[i], y, er, s=5e20))
    diff.append(fit[i](t[i]) - y)

这是这个数字:

fig = plt.figure()
for i in range(12):
    plt.subplot(4,3,i+1)
    fig.add_axes((0.,0.3,0.7,0.9))
    plt.plot(s[i], fit[i](s[i]), 'r-') # this is the fit
    plt.errorbar(t[i], y, er, fmt='.k',ms=6) # this is the data 
    plt.axis([0,1, 190, 360])

    fig.add_axes((0.,0.,0.7,0.3))       
    plot(t[i],diff[i],'or') # this are the residuals
    plt.axis([0,1, 190, 360])

如您所见,我生成了 12 个子图,在我添加 fig.add_axes 以将每个子图分隔在 data+fit 和残差之间之前效果很好,但我得到的是一个凌乱的图subplots(图已经缩小看下的subplots):

我想要的是 12 个子图,每个子图如下所示:

【问题讨论】:

    标签: python for-loop matplotlib subplot


    【解决方案1】:

    通常plt.subplot(..)fig.add_axes(..) 是互补的。这意味着这两个命令都会在图形内部创建一个轴。

    但是,它们的用法会有所不同。要使用 subplot 创建 12 个子图,您可以这样做

    for i in range(12):
        plt.subplot(4,3,i+1)
        plt.plot(x[i],y[i])
    

    要使用add_axes 创建 12 个子图,您需要执行以下操作

    for i in range(12):
        ax = fig.add_axes([.1+(i%3)*0.8/3, 0.7-(i//3)*0.8/4, 0.2,.18])
        ax.plot(x[i],y[i])
    

    需要将轴的位置传递给add_axes

    两者都工作正常。但是将它们组合起来并不简单,因为子图是根据网格定位的,而使用 add_axes 您需要已经知道网格位置。

    所以我建议从头开始。创建子图的合理且干净的方法是使用plt.subplots()

    fig, axes = plt.subplots(nrows=4, ncols=3)
    for i, ax in enumerate(axes.flatten()):
        ax.plot(x[i],y[i])
    

    每个子图可以使用轴分隔符分为 2 (make_axes_locatable)

    from mpl_toolkits.axes_grid1 import make_axes_locatable
    divider = make_axes_locatable(ax)
    ax2 = divider.append_axes("bottom", size=size, pad=pad)
    ax.figure.add_axes(ax2)
    

    因此,在轴上循环并对每个轴执行上述操作可以获得所需的网格。

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    plt.rcParams["font.size"] = 8
    
    x = np.linspace(0,2*np.pi)
    amp = lambda x, phase: np.sin(x-phase)
    p = lambda x, m, n: m+x**(n)
    
    fig, axes = plt.subplots(nrows=3, ncols=4, figsize=(8,6), sharey=True, sharex=True)
    
    def createplot(ax, x, m, n, size="20%", pad=0):
        divider = make_axes_locatable(ax)
        ax2 = divider.append_axes("bottom", size=size, pad=pad)
        ax.figure.add_axes(ax2)
        ax.plot(x, amp(x, p(x,m,n)))
        ax2.plot(x, p(x,m,n), color="crimson")
        ax.set_xticks([])
    
    for i in range(axes.shape[0]):
        for j in range(axes.shape[1]):
            phase = i*np.pi/2
            createplot(axes[i,j], x, i*np.pi/2, j/2.,size="36%")
    
    plt.tight_layout()        
    plt.show()
    

    【讨论】:

    • 抱歉解释不佳,我已经编辑了我的问题以使其更清楚。我混合了这两种方法,试图在同一个子图中绘制我的数据+拟合和残差
    • 哦,伙计,这与最初的问题完全不同。 ;-) 我稍后会调查。
    • 这太棒了!我花了一段时间来实现它,但现在它工作得很好。还有一件事,我可以使用pyplot.axis 控制绘图底部的轴限制,但我还没有设法使其适用于上部。关于处理轴限制的任何建议?
    • 当使用像这里这样的多个轴时,最好不要使用 pyplot(因为您将无法知道当前轴是哪个轴,您正在处理。)。最好直接在轴上工作:ax.set_xlim(0,4)ax2.set_xlim(5,10)ylim 相同。或ax.axis([0,4,0,1])ax2.axis([0,4,0,1])
    猜你喜欢
    • 2022-01-16
    • 2020-07-21
    • 2016-08-18
    • 2015-06-22
    • 2020-10-22
    • 2016-10-20
    • 1970-01-01
    • 2015-06-16
    相关资源
    最近更新 更多