最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - How to display a colorbar with custom normalized colormap? - Stack Overflow

programmeradmin2浏览0评论

I've plotted a scatter with custom colormap's normalization. Scatter appears right. After that, I've added a colorbar and I want the colors on this colorbar will be same as on the scatter. There is my code:

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

class SigmoidNormalize(mpl.colors.Normalize):
    def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
        if vcenter is None:
            self.vcenter = (vmax+vmin) / 2
        self.vcenter = vcenter
        super().__init__(vmin, vmax, clip)

    def __call__(self, value, clip=None):
        threshold = self.vcenter
        value = (value - threshold) * 10
        norm = 1 / (1+np.exp(-value))
        return norm
        

    def inverse(self, value):
        threshold = self.vcenter
        nonzero = np.logical_and(value != 0, value != 1)
        norm = np.empty_like(value)
        norm[nonzero] = -np.log(1/value[nonzero] - 1)
        norm[nonzero] = norm[nonzero] / 10 + threshold
        norm[value==0] = self.vmin
        norm[value==1] = self.vmax
        return norm

class SigmoidNormalize_r(SigmoidNormalize):
    def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
        super().__init__(vmin, vmax, vcenter, clip)
    
    def __call__(self, value, clip=None):
        return super().inverse(value)
        
    def inverse(self, value):
        return super().__call__(value)

def plot_predictions(predictions, 
                     actual, 
                     threshold=0.5, 
                     threshold_gap=0.1):
    fig = plt.figure()
    ax = fig.add_subplot()
    normals = np.where(np.logical_and(actual == 0, predictions < threshold))[0]
    abnormals = np.where(np.logical_and(actual == 1, predictions >= threshold))[0]
    normals_wrong = np.where(np.logical_and(actual == 0, predictions > threshold))[0]
    abnormals_wrong = np.where(np.logical_and(actual == 1, predictions <= threshold))[0]
    
    cmap = mpl.cm.rainbow
    norm = SigmoidNormalize(vmin=0, vmax=1, vcenter=threshold-threshold_gap)
    norm_r = SigmoidNormalize_r(vmin=0, vmax=1, vcenter=threshold-threshold_gap)
    # Artist's zorder is just a scalar and cannot be applied to
    # each point in scatter, so we need to draw right and wrong
    # predictions separately, to place wrong predictions on the top
    # and make it's visibility more clean.
    ax.scatter(predictions[normals], normals, 
               c=predictions[normals],
               norm=norm,
               cmap=cmap)
    ax.scatter(predictions[abnormals], abnormals, 
               c=1-predictions[abnormals],
               norm=norm,
               cmap=cmap)
    ax.scatter(predictions[normals_wrong], normals_wrong, 
               c=predictions[normals_wrong],
               norm=norm,
               cmap=cmap)
    ax.scatter(predictions[abnormals_wrong], abnormals_wrong, 
               c=1-predictions[abnormals_wrong],
               norm=norm,
               cmap=cmap)
    
    ax.axvline(threshold, color='red', linestyle='--', linewidth=1)
    ax.set_xlim((0, 1))
    fig.colorbar(mpl.cm.ScalarMappable(norm=norm_r, cmap=cmap), ax=ax,
                 orientation='horizontal')

if __name__ == '__main__':
    predictions1 = np.abs(np.random.normal(0, 0.25, 1000))
    predictions2 = 1-np.abs(np.random.normal(0, 0.25, 1000))
    actual1 = np.full_like(predictions1, 0)
    actual2 = np.full_like(predictions2, 1)
    predictions = np.concatenate((predictions1, predictions2))
    actual = np.concatenate((actual1, actual2))
    gen = np.random.Generator(np.random.MT19937())
    con = np.array([predictions, actual])
    gen.shuffle(con, axis=1)
    predictions, actual = con
    plot_predictions(predictions, actual)

There is what I've got:

The greater the difference between predictions and actuals, the closer the color is to red. On the plot we can see that at the center of the graph the points are orange, while on the colorbar they are green. We need to adjust the colorbar so that it also has orange in the middle and red on the right side. The labels should be uniform, but if this is not possible, just remove them.

There is what I want:

发布评论

评论列表(0)

  1. 暂无评论