y values in a bar plot according to a colormap

2019-04-12 16:43发布

问题:

I have already searched on the forum, finding this, but my question is bit different. As you can see from the code and the image below, I have created a map with colormap "virdis". How can I create individual bar-plots with the same colormap? I would like to color the 4 color-bars (that now are colored with simple colors) so that the values on the y axes correspond to those of the colorbar, is it possible?

I have this matrix:

matrix=[[ 0 0 0 0 17 25 29 35 36 41] [16 22 17 10 9 21 23 27 26 22] [ 8 19 13 16 13 5 4 11 5 4] [ 3 11 10 8 7 1 0 0 0 0]]

in this code:

fig, ax = plt.subplots(figsize=(7, 10))

im = ax.imshow(matrix, cmap='viridian')

ax.set_xticks([0,1,2,3,4,5,6,7,8,9])
ax.set_xticklabels(['0.5','1.0','1.5','2.0','2.5','3.0','3.5','4.0','4.5','5.0'])
ax.set_xlabel('Redshift')
ax.set_yticks([-0.5,0.5,1.5,2.5,3.5])
ax.set_yticklabels(['50k','10k','1k','0.1k','0'])
ax.set_ylabel('counts')


divider = make_axes_locatable(ax)
axHistx1 = divider.append_axes("top", 1.2, pad=0.2, sharex=ax)
axHistx1.xaxis.set_tick_params(labelbottom=False)
axHistx2 = divider.append_axes("top", 1.2, pad=0.2, sharex=ax)
axHistx2.xaxis.set_tick_params(labelbottom=False)
axHistx3 = divider.append_axes("top", 1.2, pad=0.2, sharex=ax)
axHistx3.xaxis.set_tick_params(labelbottom=False)
axHistx4 = divider.append_axes("top", 1.2, pad=0.2, sharex=ax)
axHistx4.xaxis.set_tick_params(labelbottom=False)


cbaxes = fig.add_axes([0.125, 0.03, 0.774, 0.04])
cbar=fig.colorbar(im, label='match num.', cax = cbaxes, orientation="horizontal", boundaries=np.linspace(0,50,1001),
                  ticks=[0,10,20,30,40,50])
cbar.set_clim(0,50)


#print(matrix)
row0 = np.array(matrix[0,:])
row1 = np.array(matrix[1,:])
row2 = np.array(matrix[2,:])
row3 = np.array(matrix[3,:])
col0 = np.array(matrix[:,0]).T
col1 = np.array(matrix[:,1]).T
col2 = np.array(matrix[:,2]).T
col3 = np.array(matrix[:,3]).T
col4 = np.array(matrix[:,4]).T
col5 = np.array(matrix[:,5]).T
col6 = np.array(matrix[:,6]).T
col7 = np.array(matrix[:,7]).T
col8 = np.array(matrix[:,8]).T
col9 = np.array(matrix[:,9]).T

zbin = [0,1,2,3,4,5,6,7,8,9]
row0 = row0.ravel();row1 = row1.ravel();row2 = row2.ravel();row3 = row3.ravel();

axHistx1.bar(zbin, row3, color='orange', alpha=0.5, edgecolor=['orange']*len(zbin))
axHistx1.set_ylim(0,50)
axHistx1.set_ylabel('match')
axHistx2.bar(zbin, row2, color='r', alpha=0.5, edgecolor=['r']*len(zbin))
axHistx2.set_ylim(0,50)
axHistx2.set_ylabel('match')
axHistx3.bar(zbin, row1, color='g', alpha=0.5, edgecolor=['g']*len(zbin))
axHistx3.set_ylim(0,50)
axHistx3.set_ylabel('match')
axHistx4.bar(zbin, row0, color='cornflowerblue', alpha=0.8, edgecolor=['cornflowerblue']*len(zbin))
axHistx4.set_ylim(0,50)
axHistx4.set_ylabel('match')
ax.axis('tight')

plt.show()

回答1:

To colorize bars you could loop over the bars and set the color. This is shown e.g. in this question Plot histogram with colors taken from colormap for histograms. For bars it is easier, as shown e.g. in How can I convert numbers to a color scale in matplotlib?

bars = plt.bar(x, y, color=list_of_colors)

Now you need to find out which color you would actually like to give the bars. To this end you would rely on the colormap and the norm from the image which is produced earlier on,

plt.bar(x, y, color=im.cmap(im.norm(y)))

Using loops to get rid of the redundant code would also make sense as well using subplots instead of make_axes_divisable.

import numpy as np
import matplotlib.pyplot as plt


matrix=[[ 0,  0,  0,  0, 17, 25, 29, 35, 36, 41],
     [16, 22, 17, 10,  9, 21, 23, 27, 26, 22],
     [ 8, 19, 13, 16, 13,  5,  4, 11,  5,  4],
     [ 3, 11, 10,  8,  7,  1,  0,  0,  0,  0]]

fig, axes = plt.subplots(nrows = 5, sharex=True, figsize=(6, 8),
                         gridspec_kw=dict(height_ratios=[1,1,1,1,3]))
fig.subplots_adjust(top=0.95, bottom=0.05)
ax = axes[-1]
im = ax.imshow(matrix, cmap='viridis', aspect="auto")

ax.set_xticks([0,1,2,3,4,5,6,7,8,9])
ax.set_xticklabels(['0.5','1.0','1.5','2.0','2.5','3.0','3.5','4.0','4.5','5.0'])
ax.set_xlabel('Redshift')
ax.set_yticks([-0.5,0.5,1.5,2.5,3.5])
ax.set_yticklabels(['50k','10k','1k','0.1k','0'])
ax.set_ylabel('counts')

#cbaxes = fig.add_axes([0.125, 0.03, 0.774, 0.04])
cbar=fig.colorbar(im, label='match num.', ax = axes[-1],  pad=0.2,
                  orientation="horizontal", boundaries=np.linspace(0,50,1001),
                  ticks=[0,10,20,30,40,50])
cbar.set_clim(0,50)

zbin = [0,1,2,3,4,5,6,7,8,9]

for i, ax in enumerate(axes[:-1]):
    y = np.array(matrix)[i,:]
    bars = ax.bar(zbin, y, color=im.cmap(im.norm(y)))
    ax.set_ylim(0,50)
    ax.set_ylabel('match')

plt.show()