Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make heatmap square in Seaborn FacetGrid

I'm using Seaborn's FacetGrid class to plot a set of matrices using the heatmap function, also from Seaborn. However, I cannot adjust the aspect ratio of these subplots. Here is an example:

import seaborn as sns import numpy as np import pandas as pd  # Generate a set of sample data np.random.seed(0) indices = pd.MultiIndex.from_product((range(5), range(5), range(5)), names=('label0', 'label1', 'label2')) data = pd.DataFrame(np.random.uniform(0, 100, size=len(indices)), index=indices, columns=('value',)).reset_index()  def draw_heatmap(*args, **kwargs):     data = kwargs.pop('data')     d = data.pivot(index=args[1], columns=args[0], values=args[2])     sns.heatmap(d, **kwargs)  fg = sns.FacetGrid(data, col='label0') fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False) 

That produces this image:

horizontal array of plots

Notice how the elements of the matrix plots are rectangular, rather than square. If I were making one plot (without the FacetGrid), I could pass the option square=True to sns.heatmap to make the plot square. However, if I put that in the arguments to map_dataframe, I get this result:

fg = sns.FacetGrid(data, col='label0') fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False, square=True) 

array of plots made with square option

It looks like the axes are too big for the data, even though the default aspect ratio for the FacetGrid is 1. (And explicitly setting aspect=1 when constructing the FacetGrid doesn't help.)

Is there any way to fix this?

like image 438
jb326 Avatar asked Jan 04 '17 18:01

jb326


People also ask

How do you use FacetGrid in Seaborn?

Plotting Small Multiples of Data SubsetsA FacetGrid can be drawn with up to three dimensions − row, col, and hue. The first two have obvious correspondence with the resulting array of axes; think of the hue variable as a third dimension along a depth axis, where different levels are plotted with different colors.

What is FacetGrid size?

The size and shape of the plot is specified at the level of each subplot using the height and aspect parameters: g = sns. FacetGrid(tips, col="day", height=3.5, aspect=. 65) g.


1 Answers

When you set aspect argument of FacetGrid not only axis limits but the sizes and positions of axis labels and titles are also took into consideration to calculate proper axis geometry. Therefore heatmaps are rectangles.

To adjust quadratic heatmap and axis you may set corrected axis bounding box position manually with function set_bbox.

Another way is a little bit tricky. Function ax.set_aspect with the second argument box_forced would try to adjust heatmap and axis. However to completely remove remain gray borders you may hide it by setting axis background color according to figure face color like here:

import seaborn as sns import numpy as np import pandas as pd import matplotlib.pylab as plt  # Generate a set of sample data np.random.seed(0) indices = pd.MultiIndex.from_product((range(5), range(5), range(5)),  names=('label0', 'label1', 'label2')) data = pd.DataFrame(np.random.uniform(0, 100, size=len(indices)),  index=indices, columns=('value',)).reset_index()  def draw_heatmap(*args, **kwargs):     data = kwargs.pop('data')     d = data.pivot(index=args[1], columns=args[0], values=args[2])     sns.heatmap(d, **kwargs)  fg = sns.FacetGrid(data, col='label0') fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False, square = True) # get figure background color facecolor=plt.gcf().get_facecolor() for ax in fg.axes.flat:     # set aspect of all axis     ax.set_aspect('equal','box-forced')     # set background color of axis instance     ax.set_axis_bgcolor(facecolor) plt.show() 

Result:

enter image description here

like image 102
Serenity Avatar answered Sep 21 '22 06:09

Serenity