4

this is my first post here!

I'm using calmap to plot nice calendar plot to analyze some data. The calendar plot is using a colormap to show contrast between days. The problem I have is that calmap does not provide friendly tool to display a colorbar associated with the calendar plot. I would like to know if one of you have a solution to this. The ideal would be that the colorbar is set for the entire figure and not only one axis.

the documentation of calmap :http://pythonhosted.org/calmap/

import pandas as pd

import numpy as np

import calmap # pip install calmap

%matplotlib inline

df=pd.DataFrame(data=np.random.randn(500,1)
                ,index=pd.date_range(start='2014-01-01 00:00:00',freq='1D',periods =500)
                ,columns=['data'])

fig,ax=calmap.calendarplot(df['data'],
                    fillcolor='grey', linewidth=0,cmap='RdYlGn',
                    fig_kws=dict(figsize=(17,8)))

fig.suptitle('Calendar view' ,fontsize=20,y=1.08)

the calmap plot example

enter image description here

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
ABreit
  • 43
  • 1
  • 5

2 Answers2

10

Digging into calmap code here martijnvermaat/calmap I understand that

  • calendarplot calls several yearplot for each subplot (twice in your case)
  • yearplot create a first ax.pcolormesh with background and then another one with the actual data, plus a bunch of other thing.

To dig into the object related to an axis you can use (I assume your code import and data initialization before anything here) :

ax[0].get_children()

[<matplotlib.collections.QuadMesh at 0x11ebd9e10>,
 <matplotlib.collections.QuadMesh at 0x11ebe9210>, <- that's the one we need!
 <matplotlib.spines.Spine at 0x11e85a910>,
 <matplotlib.spines.Spine at 0x11e865250>,
 <matplotlib.spines.Spine at 0x11e85ad10>,
 <matplotlib.spines.Spine at 0x11e865490>,
 <matplotlib.axis.XAxis at 0x11e85a810>,
 <matplotlib.axis.YAxis at 0x11e74ba90>,
 <matplotlib.text.Text at 0x11e951dd0>,
 <matplotlib.text.Text at 0x11e951e50>,
 <matplotlib.text.Text at 0x11e951ed0>,
 <matplotlib.patches.Rectangle at 0x11e951f10>]

now, we can use fig.colorbar (plt.colorbar is a wrapper around this function) as suggested in this answer Matplotlib 2 Subplots, 1 Colorbar :

fig,ax=calmap.calendarplot(df['data'],
                    fillcolor='grey', linewidth=0,cmap='RdYlGn',
                    fig_kws=dict(figsize=(17,8)))

fig.colorbar(ax[0].get_children()[1], ax=ax.ravel().tolist())

this produces a vertical colobar referencing color the only in the first plot, but the color are the same for all the plots.

enter image description here

I'm still playing with position better the axis and an horizontal one, but it should be easy from here.

As bonus, for a single yearplot:

fig = plt.figure(figsize=(20,8))
ax = fig.add_subplot(111)
cax = calmap.yearplot(df, year=2014, ax=ax, cmap='YlGn')
fig.colorbar(cax.get_children()[1], ax=cax, orientation='horizontal')

enter image description here

Community
  • 1
  • 1
kidpixo
  • 516
  • 7
  • 13
3

Putting together @kidpixo answer and this answer from @bogatron, I prepared a self contained example that 'does the obvious thing', creating a colorbar on the right side of the calmap and matching its height.

import pandas as pd
import numpy as np
import calmap # pip install calmap
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
%matplotlib inline

df=pd.DataFrame(data=np.random.randn(500,1)
                ,index=pd.date_range(start='2014-01-01 00:00:00',freq='1D',periods =500)
                ,columns=['data'])

fig = plt.figure(figsize=(20,8))
ax = fig.add_subplot(111)
cax = calmap.yearplot(df.data, year=2014, ax=ax, cmap='YlGn')
# fig.colorbar(cax.get_children()[1], ax=cax, orientation='horizontal')
divider = make_axes_locatable(cax)
lcax = divider.append_axes("right", size="2%", pad=0.5)
fig.colorbar(cax.get_children()[1], cax=lcax)

example calmap with side colorbar

RobM
  • 1,005
  • 11
  • 13