matplotlib相邻子图:添加颜色栏会更改子图的大小

时间:2019-05-22 13:06:18

标签: python matplotlib colorbar

我正在尝试绘制一个由5 x 6个子图组成的图形,这些图我都希望相邻,即共享它们的x和y轴。

我还想在每行的最右边绘图中添加一个颜色条,该颜色条已针对该行中的所有子图进行了标准化。

我使用以下方法添加颜色条:

<!DOCTYPE html>
<html>

<head>
  <script src="http://d3js.org/d3.v4.min.js"></script>
</head>


<body>
  <div id="grid"></div>

  <script>
    //creat 1670 numbers of matrices with size of 180*90
    var myMatrix = new Array(1670)
    for (var i = 0; i < 1670; i++) {
      myMatrix[i] = twodmatrix()
    }

    function twodmatrix() {
      var myMat = new Array(180)
      for (var i = 0; i < 180; i++) {
        myMat[i] = new Array(90)
      }
      return (myMat)
    }

    //read from file

    d3.text("tempanomaly_new.txt", function(data) {
      myMatrix = data
    })




    // save the values of one matrix in color matrix


    const NUM_COLOR = 16200;

    var colorArr = new Array(NUM_COLOR);
    for (var i = 0; i < NUM_COLOR; i++) {
      colorArr[i] = getColor();

    }

    function getColor() {
      color = "#" + [Math.floor(Math.values(myMatrix) * 16)];
      return color;
    }

    const BLOCK_SIZE = 30;
    const BLOCK_SPACE = 5;
    var gridData = new Array(180)
    for (var i = 0; i < 180; i++) {
      gridData[i] = new Array(90)
      for (var j = 0; j < 90; j++) {
        gridData[i][j] = {
          x: (i + 1) * BLOCK_SIZE + BLOCK_SPACE,
          y: (j + 1) * BLOCK_SIZE + BLOCK_SPACE,
          size: BLOCK_SIZE,
          color: colorArr[(i * 10 + j) % NUM_COLOR]
        }

      }
    }

    var grid = d3.select("#grid")
      .append("svg")
      .attr("width", "100%")
      .attr("height", "100%")
      .style("color", "#b2b2b2");


    var row = grid.selectAll(".row")
      .data(gridData)
      .enter().append("g")
      .attr("class", "row");


    var column = row.selectAll(".square")
      .data(function(data) {
        return data;
      })
      .enter()
      .append("rect")
      .attr("class", "square")
      .attr("x", function(data) {
        return data.x;
      })
      .attr("y", function(data) {
        return data.y;
      })
      .attr("width", function(data) {
        return data.size;
      })
      .attr("height", function(data) {
        return data.size;
      })
      .style("fill", function(data) {
        return data.color;
      })
      .style("stroke", "#222");
  </script>
</body>

</html>

但是,添加颜色栏会更改子图的大小,并且不再粘到其他子图上。这是一个示例输出: sample output, generated with the program below 添加彩条时如何不改变尺寸?

以下是生成上面图像的代码示例:

   divider = make_axes_locatable(ax)
   cax = divider.append_axes("right", size="5%", pad=0.15)
   fig.colorbar(im, cax=cax)

1 个答案:

答案 0 :(得分:0)

实际上,下面来自用户ImportanceOfBeingErnest的注释并使用axes_grid1,我可以使其正常工作。

主要区别:对于每一行,我定义一个ImageGrid对象:

    axrows = [[] for r in range(nrows)]
    i = 0
    for r in range(nrows):
        axcols = [None for c in range(ncols)]

        axcols = ImageGrid(fig, (nrows, 1, r+1),
                    nrows_ncols=(1, ncols), 
                    axes_pad = 0.0,
                    share_all = True,
                    label_mode = 'L',
                    cbar_mode = 'edge',
                    cbar_location = 'right',
                    cbar_size = "7%",
                    cbar_pad = "2%")
        axrows[r] = axcols

然后,在代码中的正确位置,我将色条添加为

axcols.cbar_axes[0].colorbar(im)

这是完整的代码:

#!/usr/bin/env python3

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
from mpl_toolkits.axes_grid1 import make_axes_locatable, axes_size 
from mpl_toolkits.axes_grid1 import ImageGrid

# border limits for plots
lowlim = 0.43
uplim = 0.52
nx = 10


kernels = ['cubic_spline', 'quintic_spline',
        'wendland_C2', 'wendland_C4', 'wendland_C6']




#========================
def main():
#========================


    eta_facts = [ 0, 1, 2, 3, 4, 5 ]

    nrows = len(eta_facts)
    ncols = len(kernels)

    Ay_list = [[None for c in range(ncols)] for r in range(nrows)]



    #--------------------------------
    # Loop and compute As
    #--------------------------------
    dx = (uplim - lowlim)/nx

    for row, eta in enumerate(eta_facts):

        for col, kernel in enumerate(kernels):

            A = np.zeros((nx, nx), dtype=np.float)

            for i in range(nx):
                for j in range(nx):
                    A[j,i] = row + np.random.random()/10 # not a typo: need A[j,i] for imshow

            Ay_list[row][col] = A




    #------------------------------------
    # Now plot it
    #------------------------------------

    fig = plt.figure(figsize=(3.5*ncols+1, 3.5*nrows))



    axrows = [[] for r in range(nrows)]
    i = 0
    for r in range(nrows):
        axcols = [None for c in range(ncols)]

        axcols = ImageGrid(fig, (nrows, 1, r+1),
                    nrows_ncols=(1, ncols), 
                    axes_pad = 0.0,
                    share_all = True,
                    label_mode = 'L',
                    cbar_mode = 'edge',
                    cbar_location = 'right',
                    cbar_size = "7%",
                    cbar_pad = "2%")
        axrows[r] = axcols



    cmap = 'YlGnBu_r'

    lw = 2


    for row in range(nrows):
        axcols = axrows[row]

        minval = min([np.min(Ay_list[row][c]) for c in range(ncols)])
        maxval = max([np.max(Ay_list[row][c]) for c in range(ncols)])


        for col, ax in enumerate(axcols):

            im = ax.imshow(Ay_list[row][col], origin='lower', 
                vmin=minval, vmax=maxval, cmap=cmap,
                extent=(lowlim, uplim, lowlim, uplim),
                #  norm=matplotlib.colors.SymLogNorm(1e-3),
                zorder=1)

            ax.set_xlim((lowlim,uplim))
            ax.set_ylim((lowlim,uplim))


            # cosmetics
            if col > 0:
                left = False
            else:
                left = True
            if row == len(eta_facts)-1 :
                bottom = True
            else:
                bottom = False

            ax.tick_params(
                axis='both',        # changes apply to the x-axis
                which='both',       # both major and minor ticks are affected
                bottom=bottom,      # ticks along the bottom edge are off
                top=False,          # ticks along the top edge are off
                left=left,          # ticks along the left edge are off
                right=False,        # ticks along the rigt edge are off
                labelbottom=bottom, # labels along the bottom edge are off
                labeltop=False,     # labels along the top edge are off
                labelleft=left,     # labels along the left edge are off
                labelright=False)   # labels along the right edge are off


            if row==0:
                ax.set_title(kernels[col] + ' kernel', fontsize=14)
            if col==0:
                ax.set_ylabel(r"$\eta = $ "+str(eta_facts[row])+r"$\eta_0$")
        axcols.cbar_axes[0].colorbar(im)


    fig.suptitle(r"Some title", fontsize=18)
    plt.tight_layout(rect=(0, 0, 1, 0.97))
    plt.subplots_adjust(wspace=0.0, hspace=0.0)
    plt.savefig('for_stackexchange.png', dpi=150)
    plt.close()

    print('finished.')

    return





if __name__ == '__main__':
    main()

哪个产生这张图片:

results