GridSpec轴调整大小

时间:2015-03-17 16:25:46

标签: python matplotlib

我环顾四周无济于事,但我遇到了一个问题,我的python GridSpec多重插槽不断改变轴。主要问题是即使我明确设置了2dheatmap的范围和方面,它仍然会更改x轴,以便我的图形周围有空白区域。

我试过关闭自动缩放,但这会导致侧翼直方图出错,大概是因为共享轴?

def hist2d_flanking1d(x, y, xlims, ylims, bins=50, 
    weights=None,xlabel="xlabel", ylabel="ylabel", cbarlabel='Testing'):

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.ticker import NullFormatter, MaxNLocator
    from numpy import linspace
    import matplotlib.gridspec as gridspec
    from matplotlib import cm as cm
    import pdb
    from matplotlib import ticker
    from mpl_toolkits.axes_grid1 import make_axes_locatable


    plt.close('all')
    fig = plt.figure()
    gs = gridspec.GridSpec(2,2, width_ratios=[3,1], height_ratios=[1,3])
    axTemperature = plt.subplot(gs[1,0])

    # Find the min/max of the data
    xmin = np.float(xlims[0])
    xmax = np.float(xlims[1])
    ymin = np.float(ylims[0])
    ymax = np.float(ylims[1])

    xbins = linspace(start = xmin, stop = xmax, num = bins)
    ybins = linspace(start = ymin, stop = ymax, num = bins)
    H, xedges,yedges = np.histogram2d(y,x,bins=(ybins,xbins), weights=weights)
      extent=[xmin,xmax,ymin,ymax]
    cax = (axTemperature.imshow(H, extent=extent,
    interpolation='nearest', origin='lower',aspect=((xmax-xmin)/(ymax-ymin)),
    cmap=cm.cubehelix_r))

    #Set up the plot limits
    axTemperature.set_xlim(xmin,xmax)
    axTemperature.set_ylim(ymin,ymax)
    axTemperature.set_xlabel(xlabel, fontsize=22, labelpad=20)
    axTemperature.set_ylabel(ylabel, fontsize=22, labelpad=20)
    #Make the tickmarks pretty
    ticklabels = axTemperature.get_xticklabels()
    for label in ticklabels:
        label.set_fontsize(18)

    ticklabels = axTemperature.get_yticklabels()
    for label in ticklabels:
        label.set_fontsize(18)

    # Now setup the two flanking histograms
    axHistx = plt.subplot(gs[0,0], sharex=axTemperature)
    axHisty = plt.subplot(gs[1,1], sharey=axTemperature)

    # Remove the inner axes numbers of the histograms
    plt.setp(axHisty.get_yticklabels(), visible=False)
    plt.setp(axHistx.get_xticklabels(), visible=False)

    # Add labels
    axHistx.set_ylabel('N', fontsize=22, labelpad=20)
    axHisty.set_xlabel('N', fontsize=22, labelpad=20)

    #Plot the histograms
    axHistx.hist(x, bins=xbins, color = 'blue', histtype='step')
    axHisty.hist(y, bins=ybins, orientation='horizontal', color     ='red',histtype='step')

    # Make the tickmarks pretty
    ticklabels = axHistx.get_yticklabels()
    for label in ticklabels:
        label.set_fontsize(18)

    # Make the tickmarks pretty
    ticklabels = axHisty.get_xticklabels()
    for label in ticklabels:
        label.set_fontsize(18)

    #Cool trick that changes the number of tickmarks for the histogram axes
    axHisty.xaxis.set_major_locator(MaxNLocator(1))
    axHistx.yaxis.set_major_locator(MaxNLocator(1))

    # This should create an axes on the rightside of the vertical
    # histogram. Width is argument 2, padding argument 3, reduce
    # the number of ticks to make it less messy
    divider = make_axes_locatable(axHisty)
    extend = divider.append_axes("right", "20%", pad=0.2)
    cb = plt.colorbar(cax, cax=extend)
    tick_locator = ticker.MaxNLocator(nbins=5)
    cb.locator = tick_locator
    cb.update_ticks()

    # Have to draw first, then tightlayout then draw again, otherwise
    # the axes labels are cut off. If you do it before drawing it
    # complains that CGContextRef is NULL
    plt.draw()
    gs.tight_layout(fig)
    plt.draw()

    return axTemperature, axHistx, axHisty

我无法向您展示结果,因为我没有上传图片的声誉。


顺便说一下,我也有更改刻度号码的问题,我设置set_major_locator(MaxNLocator(1))应该(我认为)只有最大值刻度标记,但这不是't}是一致的。顶部直方图没有问题,但侧面直方图在轴上只有0。


我做了进一步调查,发现它在以下情况后发生故障:

axHistx = plt.subplot(gs[0,0], sharex=axTemperature)
axHisty = plt.subplot(gs[1,1], sharey=axTemperature)

虽然我不确定为什么这会突然破坏前一代码的轴大小。

1 个答案:

答案 0 :(得分:0)

在创建多重绘图的其他部分时,会重新调整中心图的x轴。这会在调用imshow时覆盖您的宽高比定义。而不是:

aspect=((xmax-xmin)/(ymax-ymin))

使用:

aspect='auto'

有关imshow的不同宽高比设置的演示,请参阅this answer


MaxNLocator(1)决定最好的刻度是第一个。要仅获得最大/最后一个刻度,可以将所有先前的刻度设置为空字符串。为此,请替换此块:

# Make the tickmarks pretty
ticklabels = axHistx.get_yticklabels()
for label in ticklabels:
    label.set_fontsize(18)

# Make the tickmarks pretty
ticklabels = axHisty.get_xticklabels()
for label in ticklabels:
    label.set_fontsize(18)

#Cool trick that changes the number of tickmarks for the histogram axes
axHisty.xaxis.set_major_locator(MaxNLocator(1))
axHistx.yaxis.set_major_locator(MaxNLocator(1))  

with:

yticklabels=axHistx.get_yticks().tolist()
yticklabels[:-1] = [' '] * len(yticklabels[:-1])
yticklabels[-1] = '{0:.0f}'.format(yticklabels[-1])

axHistx.set_yticklabels(yticklabels,fontsize=18)

xticklabels=axHisty.get_xticks().tolist()
xticklabels[:-1] = [' '] * len(xticklabels[:-1])
xticklabels[-1] = '{0:.0f}'.format(xticklabels[-1])

axHisty.set_xticklabels(xticklabels,fontsize=18)

此处,首先检索刻度标签(参见this answer)。接下来,除了最后一个之外的所有都被设置为空字符串,最后一个被格式化为整数表示。最后,重新应用标签。


您使用以下测试数据获得的图表:

x = np.random.randn(100000)
y = np.random.randn(100000)+5

xlims = [0,1]
ylims = [0,5]

axTemperature, axHistx, axHisty = hist2d_flanking1d(x, y, 
                                                    xlims, ylims, 
                                                    bins=50, weights=None, 
                                                    xlabel="xlabel", 
                                                    ylabel="ylabel", 
                                                    cbarlabel='Testing')

看起来像这样:

final figure


this answer中所述,您可以使用此命令保持已定义的宽高比:

axTemperature.set(adjustable='box-forced')

然而,这不会转化为顶部图的宽度被调整,左列中的x轴将不对齐。这里提到完整性。