Search code examples
pythonmatplotlibplotwidthcolorbar

To decrease the width of a colorbar when cax is already specified


I am plotting using matplotlib but my colorbar width is not matching with the plot the width of colorbar is very large and the labels are getting cut out. It is not fully visible. I have already positioned the colorbar by using cax. ut eventhough I put very small length in it it is not reducing. If I change the length too the width is same ,no change.I am dispalying my code here.

import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import matplotlib.ticker as mtickerenter code here
d1=xr.open_dataset('ucomp_2018daily.nc')
uf=d1.u
vf=d3.v
qf=d5.q
qf=qf*1000
lon=d1.lon
lat=d1.lat
lev=np.arange(5,250,45)
title=np.arange(7)
title=['1000hpa','925hpa','850hpa','700hpa','600hpa','500hpa','400hpa']
fig=plt.figure(figsize=(15,5),facecolor="w")
for k in range (7):
    level=['1e+05','9.25e+04', '8.5e+04', '7e+04', '6e+04', '5e+04', '4e+04']#
    qfd=qf.resample(time='1D').mean().sel(plev=(level[k]))
    ufd=uf.resample(time='1D').mean().sel(plev=(level[k]))
    vfd=vf.resample(time='1D').mean().sel(plev=(level[k]))
    sdate='2018-08-08'
    edate='2018-08-17'
    qfd=qfd.sel(time=slice(sdate,edate)).mean('time')
    ufd=ufd.sel(time=slice(sdate,edate)).mean('time')
    vfd=vfd.sel(time=slice(sdate,edate)).mean('time')
    qfds=qfd*qfd
    ufds=ufd*ufd
    vfds=vfd*vfd
    magf=np.sqrt((qfds*ufds)+(qfds*vfds))
    qfds=qfds.drop('plev')
    ufds=ufds.drop('plev')
    vfds=vfds.drop('plev')
    magf=magf.drop('plev')
    ax=fig.add_subplot(1,7,k+1,projection=ccrs.PlateCarree())
    ax.gridlines(linewidth=0,color='None',linestyle=':')
   gl=ax.gridlines(draw_labels=True)
   gl.top_labels=False
   gl.right_labels=False
   gl.xlabel_style={'size':10}
   gl.ylabel_style={'size':10}
   sh=plt.contourf(lon,lat,magf[:,:],cmap=plt.cm.GnBu,levels=lev, extend='both')
   gl.xlocator=mticker.FixedLocator([60,70,80,90,100])
   gl.yloctor=mticker.FixedLocator([-10,0,10,20,30,40])
   if k==1 or k==2 or k==3 or k==4 or k==5 or k==6 or k==7:
     gl.left_labels=False 
   if k==0:
    gl.left_labels=True
  ax.coastlines(linewidth=2, color='k')
  plt.title(title[k],fontsize=10)
  scalef=None
  


cbar=fig.colorbar(sh,cax=fig.add_axes([0.12,0.0605,0.8,0.06051]),orientation='horizontal',aspect=5,shrink=0.2)
cbar.ax.tick_params(labelsize=10)
cbar.ax.set_title('kg/ms', fontsize=10)
ax.quiverkey(qu,X=0.9,Y=1.18,U=100,label='100kg/ms',labelpos='W')

I have used shrink and aspect for decreasing the width but none of it is working. My plot is given below

colorbar width very large


Solution

  • You can change the size of the colorbar directly by modifying the cax. You currently have:

    cax=fig.add_axes([0.12,0.0605,0.8,0.06051])
    

    Those 4 numbers are:

    • x-coord of bottom left corner (0.12)
    • y-coord of bottom left corner (0.0605)
    • width (in fraction of the figure size) (0.8)
    • height (in fraction of the figure size) (0.06051)

    So, if you want the vertical dimension of the colorbar to be smaller, reduce the 4th number: e.g.:

    cax=fig.add_axes([0.12,0.0605,0.8,0.03051])
    

    would give you a thinner colorbar.

    If you want to change the horizontal extent, modify the 3rd number:

    cax=fig.add_axes([0.12,0.0605,0.4,0.06051])
    

    would give you a colorbar that is half as wide as before.

    I reduced your example down to a minimal working example:

    import numpy as np
    import matplotlib.pyplot as plt
    
    fig = plt.figure(figsize=(15,5),facecolor="w")
    lev = np.arange(5,250,45)
    
    for k in range (7):
    
       ax = fig.add_subplot(1, 7, k+1, aspect='equal')
     
       sh=plt.contourf(np.random.rand(50, 50) * 300, cmap=plt.cm.GnBu, levels=lev, extend='both')
    
    x, y = 0.12, 0.0605
    width = 0.8
    height = 0.06051
    cax = fig.add_axes([x, y, width, height])
    
    cbar = fig.colorbar(sh, cax=cax, orientation='horizontal', aspect=5,shrink=0.2)
    
    plt.show()
    

    Which yields this:

    enter image description here

    Changing to width = 0.8, height = 0.03051 gives:

    enter image description here

    and if we use width = 0.4, height = 0.06051, we get:

    enter image description here