2

Can't figure out how to simply add colorbar to a matrix of hexbin matplotlib plots. It's a 7 by 7 matrix of plots, here's part of the code for the first row:

#importing nec. libs
import pandas as pd
from pylab import rcParams
from matplotlib import pyplot as PLT
%matplotlib inline

#reading data
dataset_cat_coded_path = 'C:/Users/IBM_ADMIN/Documents/Sberbank/dataset_cat_coded.csv'
dataset_cat_coded = pd.read_csv(dataset_cat_coded_path, encoding = 'cp1251')
test_frame = dataset_cat_coded[['opf','priority', 'sales_method_id', 'is_block_vks','sector_id', 'segment_id', 'org_type_id']]



#building figure
rcParams['figure.figsize']=30,30 #fig. size

#fig. initiation
fig = PLT.figure()

#setting parameters defining min and max luminance
vmin = 0
vmax=test_frame.shape[0]

#building a row of plots
ax1 = fig.add_subplot(7,7,2)
ax1.hexbin(test_frame.opf, test_frame.priority,C=None,gridsize=12,bins=None,mincnt=1, vmin = vmin, vmax=vmax)
ax1.set_title('priority')
ax1.set_ylabel('OPF')

ax2 = fig.add_subplot(7,7,3)
ax2.hexbin(test_frame.opf, test_frame.sales_method_id,C=None,gridsize=12,bins=None,mincnt=1, vmin = vmin, vmax=vmax)
ax2.set_title('sales_method_id')

ax3 = fig.add_subplot(7,7,4)
ax3.hexbin(test_frame.opf, test_frame.is_block_vks,C=None,gridsize=12,bins=None,mincnt=1, vmin = vmin, vmax=vmax)
ax3.set_title('is_block_vks')

ax4 = fig.add_subplot(7,7,5)
ax4.hexbin(test_frame.opf, test_frame.sector_id,C=None,gridsize=12,bins=None,mincnt=1, vmin = vmin, vmax=vmax)
ax4.set_title('sector_id')

ax5 = fig.add_subplot(7,7,6)
ax5.hexbin(test_frame.opf, test_frame.segment_id,C=None,gridsize=12,bins=None,mincnt=1, vmin = vmin, vmax=vmax)
ax5.set_title('segment_id')

ax6 = fig.add_subplot(7,7,7)
ax6.hexbin(test_frame.opf, test_frame.org_type_id,C=None,gridsize=12,bins=None,mincnt=1, vmin = vmin, vmax=vmax)
ax6.set_title('org_type_id')

#colorbar attempt
cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
fig.colorbar(ax6, cax=cbar_ax, location='bottom') here

Error text:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-17-e885eb3cd39a> in <module>()
     36 
     37 cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
---> 38 fig.colorbar(ax6, cax=cbar_ax, location='bottom')

C:\Program Files\Anaconda3\lib\site-packages\matplotlib\figure.py in colorbar(self, mappable, cax, ax, use_gridspec, **kw)
   1591                 cax, kw = cbar.make_axes(ax, **kw)
   1592         cax.hold(True)
-> 1593         cb = cbar.colorbar_factory(cax, mappable, **kw)
   1594 
   1595         self.sca(current_ax)

C:\Program Files\Anaconda3\lib\site-packages\matplotlib\colorbar.py in colorbar_factory(cax, mappable, **kwargs)
   1328         cb = ColorbarPatch(cax, mappable, **kwargs)
   1329     else:
-> 1330         cb = Colorbar(cax, mappable, **kwargs)
   1331 
   1332     cid = mappable.callbacksSM.connect('changed', cb.on_mappable_changed)

C:\Program Files\Anaconda3\lib\site-packages\matplotlib\colorbar.py in __init__(self, ax, mappable, **kw)
    878         # Ensure the given mappable's norm has appropriate vmin and vmax set
    879         # even if mappable.draw has not yet been called.
--> 880         mappable.autoscale_None()
    881 
    882         self.mappable = mappable

AttributeError: 'AxesSubplot' object has no attribute 'autoscale_None'

Resulting plot: enter image description here

  • There are tons of examples out there, so what have you tried so far? Also, you need to tell if you want to add one colorbar to the whole figure? If so, are the data limits the same for all figures? Or do you want to have one colorbar per figure? – ImportanceOfBeingErnest Nov 27 '16 at 20:54
  • Data limits are the same, so 1 colorbar for the whole figure. To be honest, if I could do it even separately before the figure, that would also be ok. Problem is I can't understand what arguments to pass in my particular case to plt.colorbar() to make it work. – Igor Chebuniaev Nov 28 '16 at 02:01
  • @ImportanceOfBeingErnest solution form the page you've referenced `cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7]) fig.colorbar(im, cax=cbar_ax) ` gives error *'AxesSubplot' object has no attribute 'autoscale_None'* – Igor Chebuniaev Nov 28 '16 at 02:14
  • Can you update the code to include what you have tried and the full traceback of the error? Does [this example](http://stackoverflow.com/a/13784887/4124317) produce the same error? If not, where is the difference? Which version of matplotlib are you using? – ImportanceOfBeingErnest Nov 28 '16 at 08:05
  • @ImportanceOfBeingErnest Thanks for sticking with this thread, sorry, was busy for a couple of days. I've updated the code, attempt to add the color bar is at the bottom, error text is also added along with the resulting plot – Igor Chebuniaev Nov 30 '16 at 06:01

1 Answers1

3

As I pointed out in the comments, this question shows how to add a colorbar.

In your code

fig.colorbar(ax6, cax=cbar_ax, location='bottom')

you try to set a colorbar to the figure without specifying to which object it should relate. Therefore you get an error, which basically tells you that you did not supply any object with a mappable.

What you need to do is to give your hexbin image to the colorbar, such that it knows which colors to actually plot.

import numpy as np
import matplotlib.pyplot as plt

n = 1000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)

fig, axes = plt.subplots(nrows=2, ncols=2)
for ax in axes.flat:
    im = ax.hexbin(x,y)

fig.subplots_adjust(right=0.8)
cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
fig.colorbar(im, cax=cbar_ax)

plt.show()
Community
  • 1
  • 1
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • Yes, thanks very much for providing the final answer! Now i'll have to figure out how to change the size of it and bring it to the bottom of the whole matrix of plots. – Igor Chebuniaev Dec 02 '16 at 00:05
  • The numbers here `fig.add_axes([0.85, 0.15, 0.05, 0.7])` determine the location and size of the colorbar. First number defines where the leftmost side of the bar should be on the horizontal axis of the whole figure, with the zero in the left bottom corner. The Second number determines the same on the vertical axis. If the number are [0.1, 0.1] than the bar will stretch from the left bottom corner. The 3rd number determines the length of the colorbar in terms of the portion of the figure (=0.5 -> colorbar stretches for half the figure). The last number determines the width in the same terms. – Igor Chebuniaev Dec 02 '16 at 06:35
  • Indeed, [`add_axes(rect)`](http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure.add_axes) takes a rectangle as input, where `rect = [left, bottom, width, height]`. Those numbers are in units of the figure coordinate system (ranging from `0,0` in the lower left corner to `1,1` in the upper right one). – ImportanceOfBeingErnest Dec 02 '16 at 11:26