Nihilum
Nihilum

Reputation: 711

Seaborn heatmap change date frequency of yticks

My problem is similar to the one encountered on this topic: Change heatmap's yticks for multi-index dataframe

I would like to have yticks every 6 months, with them being the index of my dataframe. But I can't manage to make it work.

The issue is that my dataframe is 13500*290 and the answer given in the link takes a long time and doesn't really work (see image below).

This is an example of my code without the solution from the link, this part works fine for me:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime

df = pd.DataFrame(index = pd.date_range(datetime(1984, 6, 10), datetime(2021, 1, 14), freq='1D') )

for i in range(0,290):
    df['Pt{0}'.format(i)] = np.random.random(size=len(df))
    
f, ax = plt.subplots(figsize=(20,20))
sns.heatmap(df, cmap='PuOr', vmin = np.min(np.min(df)), vmax = np.max(np.max(df)), cbar_kws={"label": "Ice Velocity (m/yr)"}) 

This part does not work for me and produces the figure below, which shouldn't have the stack of ylabels on the yaxis:

f, ax = plt.subplots(figsize=(20,20))
years = df.index.get_level_values(0)
ytickvalues = [year if index in (2, 7, 12) else '' for index, year in enumerate(years)]
sns.heatmap(df, cmap='PuOr', vmin = np.min(np.min(df)), vmax = np.max(np.max(df)), cbar_kws={"label": "Ice Velocity (m/yr)"}, yticklabels = ytickvalues) 

enter image description here

Upvotes: 4

Views: 495

Answers (1)

tdy
tdy

Reputation: 41327

Here are a couple ways to adapt that link for your use case (1 label per 6 months):

  1. Either: Show an empty string except on Jan 1 and Jul 1 (i.e., when %m%d evals to 0101 or 0701)

    labels = [date if date.strftime('%m%d') in ['0101', '0701'] else ''
              for date in df.index.date]
    
  2. Or: Show an empty string except every ~365/2 days (i.e., when row % 183 == 0)

    labels = [date if row % 183 == 0 else ''
              for row, date in enumerate(df.index.date)]
    

Note that you don't have a MultiIndex, so you can just use df.index.date (no need for get_level_values).


Here is the output with a minimized version of your df:

sns.heatmap(df, cmap='PuOr', cbar_kws={'label': 'Ice Velocity (m/yr)'},
            vmin=df.values.min(), vmax=df.values.max(),
            yticklabels=labels)

Upvotes: 4

Related Questions