Setting the size of a matplotlib ColorbarBase obje

2019-09-16 10:07发布

I have an patch collection that I'd like to display a color map for. Because of some manipulations I do on top of the colormap, it's not possible for me to define it using a matplotlib.colorbar instance. At least not as far as I can tell; doing so strips some manipulations I do with my colors that blank out patches lacking data:

cmap = matplotlib.cm.YlOrRd
colors = [cmap(n) if pd.notnull(n) else [1,1,1,1]
          for n in plt.Normalize(0, 1)([nullity for _, nullity in squares])]

# Now we draw.
for i, ((min_x, max_x, min_y, max_y), _) in enumerate(squares):
    square = shapely.geometry.Polygon([[min_x, min_y], [max_x, min_y],
                                      [max_x, max_y], [min_x, max_y]])
    ax0.add_patch(descartes.PolygonPatch(square, fc=colors[i], 
                  ec='white', alpha=1, zorder=4))

So I define a matplotlib.colorbar.ColorbarBase instance instead, which works:

matplotlib.colorbar.ColorbarBase(ax1, cmap=cmap, orientation='vertical',
                                 norm=matplotlib.colors.Normalize(vmin=0, vmax=1))

Which results in e.g.:

enter image description here

The problem I have is that I want to reduce the size of this colorbar (specifically, the shrink it down to a specific vertical size, say, 500 pixels), but I don't see any obvious way of doing this. If I had a colorbar instance, I could adjust this easily using its axis property arguments, but ColorbarBase lacks these.

For further reference:

2条回答
我命由我不由天
2楼-- · 2019-09-16 10:32

The question may be a bit old, but I found another solution that can be of help for anyone who is not willing to manually create a colorbar axes for the ColorbarBase class.

The solution below uses the matplotlib.colorbar.make_axes class to create a dependent sub_axes from the given axes. That sub_axes can then be supplied for the ColorbarBase class for the colorbar creation.

The code is derived from the matplotlib code example describe in here

Here is a snippet code:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import matplotlib.colorbar as mcbar
from matplotlib import ticker
import matplotlib.colors as mcolors


# Make some illustrative fake data:

x = np.arange(0, np.pi, 0.1)
y = np.arange(0, 2 * np.pi, 0.1)
X, Y = np.meshgrid(x, y)
Z = np.cos(X) * np.sin(Y) * 10


colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]  # R -> G -> B

n_bins = [3, 6, 10, 100]  # Discretizes the interpolation into bins

cmap_name = 'my_list'


fig, axs = plt.subplots(2, 2, figsize=(9, 7))
fig.subplots_adjust(left=0.02, bottom=0.06, right=0.95, top=0.94, wspace=0.05)
for n_bin, ax in zip(n_bins, axs.ravel()):
    # Create the colormap
    cm = LinearSegmentedColormap.from_list(cmap_name, colors, N=n_bin)
    # Fewer bins will result in "coarser" colomap interpolation
    im = ax.imshow(Z, interpolation='nearest', origin='lower', cmap=cm)
    ax.set_title("N bins: %s" % n_bin)

    cax, cbar_kwds = mcbar.make_axes(ax, location = 'right',
                              fraction=0.15, shrink=0.5, aspect=20)




    cbar = mcbar.ColorbarBase(cax, cmap=cm, 
                              norm=mcolors.Normalize(clip=False), 
                              alpha=None, 
                              values=None, 
                              boundaries=None, 
                        orientation='vertical', ticklocation='auto', extend='both', 
                        ticks=n_bins, 
                        format=ticker.FormatStrFormatter('%.2f'), 
                        drawedges=False, 
                        filled=True, 
                        extendfrac=None, 
                        extendrect=False, label='my label')




    if n_bin <= 10:
        cbar.locator = ticker.MaxNLocator(n_bin) 
        cbar.update_ticks()

    else:
        cbar.locator = ticker.MaxNLocator(5) 
        cbar.update_ticks()


fig.show()
查看更多
Anthone
3楼-- · 2019-09-16 10:34

The size and shape is defined with the axis. This is a snippet from code I have where I group 2 plots together and add a colorbar at the top independently. I played with the values in that add_axes instance until I got a size that worked for me:

 cax = fig.add_axes([0.125, 0.925, 0.775, 0.0725]) #has to be as a list - starts with x, y coordinates for start and then width and height in % of figure width
 norm = mpl.colors.Normalize(vmin = low_val, vmax = high_val)     
 mpl.colorbar.ColorbarBase(cax, cmap = self.cmap, norm = norm, orientation = 'horizontal')
查看更多
登录 后发表回答