python - GridSpec 轴调整大小

标签 python matplotlib

我环顾四周没有结果,但我遇到一个问题,我的 python GridSpec multiplot 不断改变轴。主要问题是,即使我明确设置了 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)) ,它应该(我认为)只有最大值刻度线,但这并不一致。顶部直方图没有问题,但侧面直方图的轴上只有 0。


我做了进一步的调查,发现它在以下时间后崩溃了:

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

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

最佳答案

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

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

使用:

aspect='auto'

参见this answer演示 imshow 的不同宽高比设置。


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

# 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))  

与:

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 轴不会对齐。这里提到它是为了完整性。

关于python - GridSpec 轴调整大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29104485/

相关文章:

python - 对 PySpark 中 DataFrame 的某些行应用操作(其结果取决于整个 DataFrame 中的信息)

python - 使用 Matplotlib 绘制日内烛台图

python - Python 中的 Gamma 函数图

Python:简单 OLS super 词典

python - pytest:指定pytest.ini位置的环境变量

python - 如何计算 Pandas 数据框中到周末或休息日的天数

python - 引发似乎来自调用者的异常

python - Pandas 和 Matplotlib - fill_between() 与 datetime64

python - 如何填充matplotlib中线之间的区域

python - 立即显示 matplotlib 中图形的内容