Search code examples
pythonpandasmatplotlibseaborndateformatter

Show dates on seaborn heatmap


I am trying to create a heat map from pandas dataframe using seaborn library. Here, is the code:

test_df = pd.DataFrame(np.random.randn(367, 5), 
                 index = pd.DatetimeIndex(start='01-01-2000', end='01-01-2001', freq='1D'))

ax = sns.heatmap(test_df.T)
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_minor_locator(mdates.DayLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))
ax.xaxis.set_minor_formatter(mdates.DateFormatter('%d'))

However, I am getting a figure with nothing printed on the x-axis.

enter image description here


Solution

  • Seaborn heatmap is a categorical plot. It scales from 0 to number of columns - 1, in this case from 0 to 366. The datetime locators and formatters expect values as dates (or more precisely, numbers that correspond to dates). For the year in question that would be numbers between 730120 (= 01-01-2000) and 730486 (= 01-01-2001).

    So in order to be able to use matplotlib.dates formatters and locators, you would need to convert your dataframe index to datetime objects first. You can then not use a heatmap, but a plot that allows for numerical axes, e.g. an imshow plot. You may then set the extent of that imshow plot to correspond to the date range you want to show.

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    
    df = pd.DataFrame(np.random.randn(367, 5), 
                     index = pd.DatetimeIndex(start='01-01-2000', end='01-01-2001', freq='1D'))
    
    dates = df.index.to_pydatetime()
    dnum = mdates.date2num(dates)
    start = dnum[0] - (dnum[1]-dnum[0])/2.
    stop = dnum[-1] + (dnum[1]-dnum[0])/2.
    extent = [start, stop, -0.5, len(df.columns)-0.5]
    
    fig, ax = plt.subplots()
    im = ax.imshow(df.T.values, extent=extent, aspect="auto")
    
    ax.xaxis.set_major_locator(mdates.MonthLocator())
    ax.xaxis.set_minor_locator(mdates.DayLocator())
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))
    
    fig.colorbar(im)
    plt.show()
    

    enter image description here