Making sure 0 gets white in a RdBu colorbar

2020-03-26 12:26发布

I create a heatmap with the following snippet:

import numpy as np
import matplotlib.pyplot as plt
d = np.random.normal(.4,2,(10,10))
plt.imshow(d,cmap=plt.cm.RdBu)
plt.colorbar()
plt.show()

The result is plot below: enter image description here

Now, since the middle point of the data is not 0, the cells in which the colormap has value 0 are not white, but rather a little reddish.

How do I force the colormap so that max=blue, min=red and 0=white?

2条回答
Fickle 薄情
2楼-- · 2020-03-26 12:40

Use a DivergingNorm:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors

d = np.random.normal(.4,2,(10,10))

norm = mcolors.DivergingNorm(vmin=d.min(), vmax = d.max(), vcenter=0)
plt.imshow(d, cmap=plt.cm.RdBu, norm=norm)

plt.colorbar()
plt.show()

enter image description here

Note: From matplotlib 3.2 onwards DivergingNorm will be renamed to TwoSlopeNorm

查看更多
3楼-- · 2020-03-26 12:48

A previous SO post (Change colorbar gradient in matplotlib) wanted a solution for a more complicated situation, but one of the answers talked about the MidpointNormalize subclass in the matplotlib documentation. With that, the solution becomes:

import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt

class MidpointNormalize(mpl.colors.Normalize):
    ## class from the mpl docs:
    # https://matplotlib.org/users/colormapnorms.html

    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        super().__init__(vmin, vmax, clip)

    def __call__(self, value, clip=None):
        # I'm ignoring masked values and all kinds of edge cases to make a
        # simple example...
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        return np.ma.masked_array(np.interp(value, x, y))

d = np.random.normal(.4,2,(10,10))
plt.imshow(d,cmap=plt.cm.RdBu,norm=MidpointNormalize(midpoint=0))
plt.colorbar()
plt.show()

Kudos to Joe Kington for writing the subclass, and to Rutger Kassies for pointing out the answer.

Properly normalized midpoint in the heatmap

查看更多
登录 后发表回答