Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seaborn heatmap, custom tick values

I plotting a pandas dataframe to a seaborn heatmap, and I would like to set specific y-axis ticks for specific locations.

My dataframe index is 100 rows which corresponds to a "depth" parameter, but the values in this index are not arranged with a nice interval : enter image description here I would like to set tick labels at multiples of 100. I can do this fine using :

yticks = np.linspace(10,100,10)
ylabels = np.linspace(100,1000,10)

for my dataframe which has 100 rows, with values from approx 100 - 1000, but the result is clearly not desirable, as the position of the tick labels clearly do not correspond to the correct depth values (index value), only the position in the index. enter image description here

How can I produce a heatmap where the plot is warped so that the actual depth values (index values) are aligned with the ylabels I am setting?

A complicating factor for this is also that the index values are not sampled linearly...

like image 625
Nukolas Avatar asked Dec 13 '17 01:12

Nukolas


3 Answers

My solution is a little bit ugly but it works for me. Suppose your depth data is in depth_list and num_ticks is the number of ticks you want:

num_ticks = 10
# the index of the position of yticks
yticks = np.linspace(0, len(depth_list) - 1, num_ticks, dtype=np.int)
# the content of labels of these yticks
yticklabels = [depth_list[idx] for idx in yticks]

then plot the heatmap in this way (where your data is in data):

ax = sns.heatmap(data, yticklabels=yticklabels)
ax.set_yticks(yticks)
plt.show()
like image 37
liwt31 Avatar answered Nov 05 '22 14:11

liwt31


While plotting with seaborn you have to specify arguments xticklabels and yticklabels for heatmap function. These arguments in you case have to be lists with custom tick labels.

like image 178
Serenity Avatar answered Nov 05 '22 12:11

Serenity


I have developed a solution which does what I intended, modified after liwt31's solution:

def round(n, k):
    # function to round number 'n' up/down to nearest 'k'
    # use positive k to round up
    # use negative k to round down

    return n - n % k

# note: the df.index is a series of elevation values
tick_step = 25 
tick_min = int(round(data.index.min(), (-1 * tick_step)))  # round down
tick_max = (int(round(data.index.max(), (1 * tick_step)))) + tick_step  # round up

# the depth values for the tick labels 
# I want my y tick labels to refer to these elevations, 
# but with min and max values being a multiple of 25.
yticklabels = range(tick_min, tick_max, tick_step)
# the index position of the tick labels
yticks = []
for label in yticklabels:
    idx_pos = df.index.get_loc(label)
    yticks.append(idx_pos)

cmap = sns.color_palette("coolwarm", 128)
plt.figure(figsize=(30, 10))
ax1 = sns.heatmap(df, annot=False, cmap=cmap, yticklabels=yticklabels)
ax1.set_yticks(yticks)
plt.show()
like image 1
Nukolas Avatar answered Nov 05 '22 12:11

Nukolas