7

I tried to write multiple heatmaps in one figure. I wrote the below code and I have two questions.

(1) I want the data value in each cell and I don't need the axis labels for each picture. Therefore, I set xticklabels, yticklables, and annot; but they were not reflected in the figure. How should I do? (2) Can I rotate the color bar? I need one horizontal color bar for this fifure.

I use Python 3.5.2 in Ubuntu 14.04.5 LTS.

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

%matplotlib notebook

flights = sns.load_dataset("flights")
flights = flights.pivot("month", "year", "passengers")
fig = plt.figure(figsize=(15, 8))
# integral
plt.subplot(1,2,1)
sns.set(font_scale=0.8)
plt.title('integral', fontsize = 1)
plt.subplots_adjust(top=0.90, left = 0.1)
sns.heatmap(flights, fmt='d', cmap='gist_gray_r', xticklabels = False, yticklabels = False, annot=True)

#float
plt.subplot(1,2,2)
sns.set(font_scale=0.8)
plt.title('float', fontsize = 1)
plt.subplots_adjust(top=0.90, left = 0.1)
sns.heatmap(flights, annot=True, fmt='.2f', cmap='gist_gray_r', xticklabels = False, yticklabels = False)

fig.suptitle('Title for figure', fontsize=20)
plt.subplots_adjust(top=0.9, left=0.06, bottom=0.08) #後ろ2つ追加
#x label
fig.text(0.5, 0.02, 'year', ha='center', va='center')
#y label
fig.text(0.02, 0.5, 'month', ha='center', va='center', rotation='vertical')

sns.plt.savefig('heatmap.png')

enter image description here

Vinícius Figueiredo
  • 6,300
  • 3
  • 25
  • 44
rrkk
  • 437
  • 1
  • 5
  • 15

1 Answers1

12

(1) I want the data value in each cell and I don't need the axis labels for each picture. Therefore, I set xticklabels, yticklables, and annot; but they were not reflected in the figure. How should I do?

It's a recent fixed issue that when xticklabels = False or yticklabels = False, annot = True doesn't work. A workaround is to set xticklabels and yticklabels both to a list of an empty string [""].

I made an adjustment declaring the subplots axis with fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True), which is better for understanding the code. I set all axes labels to "" with the likes of: ax1.set_ylabel(''), so after cleaning, we can make the labels we want, instead of those auto-generated with sns.heatmap. Also, the labels in the figure are better generated this way than manually set using fig.text.

(2) Can I rotate the color bar?

cbar_kws={"orientation": "horizontal"} is the argument for sns.heatmap that makes the colorbars horizontal.

Using the code below:

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

flights = sns.load_dataset("flights")
flights = flights.pivot("month", "year", "passengers")

fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)

#First

sns.heatmap(flights, ax=ax1, fmt='d', cmap='gist_gray_r', xticklabels = [""], yticklabels = [""], annot = True, cbar_kws={"orientation": "horizontal"})
ax1.set_ylabel('')    
ax1.set_xlabel('')
ax1.set_title('Integral')

#Second

sns.heatmap(flights, ax=ax2, fmt='.2f', cmap='gist_gray_r', xticklabels = [""], yticklabels = [""], annot = True, cbar_kws={"orientation": "horizontal"})
ax2.set_ylabel('')    
ax2.set_xlabel('')
ax2.set_title('Float')

ax1.set_ylabel("Month")
ax1.set_xlabel("Year")
ax2.set_xlabel("Year")

plt.show()

This generates this image:

enter image description here


If you wish to have only one big horizontal colorbar you can change the code to the following:

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

flights = sns.load_dataset("flights")
flights = flights.pivot("month", "year", "passengers")

fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)

#First

im = sns.heatmap(flights, ax=ax1, fmt='d', cmap='gist_gray_r', xticklabels = [""], yticklabels = [""], annot = True, cbar = False)
ax1.set_ylabel('')    
ax1.set_xlabel('')
ax1.set_title('Integral')

#Second

sns.heatmap(flights, ax=ax2, fmt='.2f', cmap='gist_gray_r', xticklabels = [""], yticklabels = [""], annot = True, cbar = False)
ax2.set_ylabel('')    
ax2.set_xlabel('')
ax2.set_title('Float')

ax1.set_ylabel("Month")
ax1.set_xlabel("Year")
ax2.set_xlabel("Year")

mappable = im.get_children()[0]
plt.colorbar(mappable, ax = [ax1,ax2],orientation = 'horizontal')

plt.show()

We are getting the mappable object: mappable = im.get_children()[0] and then creating a plt.colorbar using this mappable object and [ax1,ax2] as the ax paramater. I expect this to work every time, it plots the image:

Vinícius Figueiredo
  • 6,300
  • 3
  • 25
  • 44
  • 2
    I just realised you only want one big horizontal colorbar, I'll edit my answer with this solution. – Vinícius Figueiredo Jul 15 '17 at 21:23
  • 1
    I appreciate your quick responses! All of my questions were solved! The really needed figure is the combination of 10 heatmaps and I could make that on the basis of the above code. I can't understand and use mappable object appropriately yet, but I will continue to try that because one big horizontal colorbar is better. Thank you again. – rrkk Jul 16 '17 at 10:49
  • 1
    @rrkk I'm glad it helped, if it was helpful you should [accept my answer](https://meta.stackexchange.com/a/5235) by clicking on the green tick marker near the upvotes. – Vinícius Figueiredo Jul 16 '17 at 13:14
  • 1
    I'm ashamed because I sometimes forget to check the green tick mark. I've checked that. – rrkk Jul 16 '17 at 17:15