change certain squares in a seaborn heatmap

2019-02-03 19:13发布

问题:

Say I have a heatmap that looks like this (axes are trimmed off):

I want to be able to alter certain squares to denote statistical significance. I know that I could mask out the squares that are not statistically significant, but I still want to retain that information (and not set the values to zero). Options for doing this include 1) making the text on certain squares bold, 2) adding a hatch-like functionality so that certain squares have stippling, or 3) adding a symbol to certain squares.

Any ideas on this? Thanks!

回答1:

You could plot twice, applying a mask to the cells you do not want to emphasize the second time:

import numpy as np
import seaborn as sns
x = np.random.randn(10, 10)
sns.heatmap(x, annot=True)
sns.heatmap(x, mask=x < 1, cbar=False,
            annot=True, annot_kws={"weight": "bold"})


回答2:

One approach is to access the Text objects directly and change their weight/style. The below code will take some sample data and try to make every entry equal to 118 stand out:

flights = sns.load_dataset("flights")
flights = flights.pivot("month", "year", "passengers")
ax = sns.heatmap(flights, annot=True, fmt="d")

for text in ax.texts:
    text.set_size(14)
    if text.get_text() == '118':
        text.set_size(18)
        text.set_weight('bold')
        text.set_style('italic')

I'm not a matplotlib/seaborn expert, but it appears to me that requiring an individual cell in the heatmap to be hatched would require a bit of work. In short, the heatmap is a Collection of matplotlib Patches, and the hatching of a collection can only be set on the collection as a whole. To set the hatch of an individual cell, you need them to be distinct patches, and things get messy. Perhaps (hopefully) someone more knowledgeable than I can come along and say that this is wrong, and that it's quite easy -- but if I had to guess, I'd say that changing the text style will be easier than setting a hatch.