【问题标题】:How to annotate and correctly place numbers in a heatmap如何在热图中注释和正确放置数字
【发布时间】:2021-12-08 13:17:39
【问题描述】:

我遇到了热图问题。

我创建了以下函数来显示热图分析

data = [ 0.00662896, -0.00213044, -0.00156812,  0.01450994, -0.00875174, -0.01561342, -0.00694762,  0.00476027,  0.00470659]

def plot_heatmap(pathOut, data, title, fileName, precis=2, show=False):
    from matplotlib import cm
    fig  = plt.figure()
    n       = int(np.sqrt(len(data)))
    data    = data.reshape(n,n)
    heatmap = plt.pcolor(data,cmap=cm.YlOrBr)
    xLabels = (np.linspace(1,n,n,dtype=int))
    yLabels = (np.linspace(1,n,n,dtype=int))
    xpos    = np.linspace(1,n,n)-0.5
    ypos    = np.linspace(1,n,n)-0.5

    for y in range(n):
        for x in range(n):
            plt.text(x + 0.5, y + 0.5, f'{data[y, x]:.{precis}f}',
                horizontalalignment='center',
                verticalalignment='center',
                )

    plt.colorbar(heatmap, format='%.2f')
    plt.xticks(xpos,xLabels)
    plt.yticks(ypos,yLabels)
    plt.title(f'{title}')
    if (show == False ):
        plt.close(fig)        
    elif (show == True):        
        plt.show()    
    fig.savefig(f'{pathOut}/{fileName}.pdf', format='pdf')   

当我调用该函数时,热图已创建但不正确,因为我想以特定精度显示值。我知道如何定义文本精度和比例精度,但是如何调整数据精度以生成正确的热图?

在附图中,我有 7 个等于 0 的单元格,用于我想要的精度,但使用的数据具有更大的精度,会产生不同的颜色。

【问题讨论】:

    标签: python matplotlib seaborn heatmap


    【解决方案1】:
    • 使用seaborn.heatmap 更容易,其中包括注释和颜色条。 seabornmatplotlib 的高级 API。
      • 这大大减少了代码行数。
    import matplotlib.pyplot as plt
    from matplotlib import cm
    import numpy as np
    import seaborn as sns
    
    def plot_heatmap(pathOut, fileName, data, title, precis=2, show=False):
        n = int(np.sqrt(len(data)))
        data = data.reshape(n, n)
        
        xy_labels = range(1, n+1)
        
        fig, ax = plt.subplots(figsize=(8, 6))
        p = sns.heatmap(data=data, annot=True, fmt=f'.{precis}g', ax=ax,
                        cmap=cm.YlOrBr, xticklabels=xy_labels, yticklabels=xy_labels)
    
        ax.invert_yaxis()  # invert the axis if desired
        ax.set_title(f'{title}')
        fig.savefig(f'{pathOut}/{fileName}.pdf', format='pdf') 
        if (show == False ):
            plt.close(fig)        
        elif (show == True):        
            plt.show()
    
    
    data = np.array([ 0.00662896, -0.00213044, -0.00156812,  0.01450994, -0.00875174, -0.01561342, -0.00694762,  0.00476027,  0.00470659])
    
    plot_heatmap('.', 'test', data, 'test', 4, True)
    

    • plt.txt 的 f 字符串不正确。将值 round 并将其转换为 str 类型会更容易。
      • str(round(data[x, y], precis)) 而不是 f'{data[y, x]:.{precis}f}'
    • data[x, y] 应该是 data[y, x]
    import matplotlib.pyplot as plt
    from matplotlib import cm
    import numpy as np
    
    def plot_heatmap(pathOut, fileName, data, title, precis=2, show=False):
        fig  = plt.figure(figsize=(8, 6))
        n       = int(np.sqrt(len(data)))
        data    = data.reshape(n, n)
        heatmap = plt.pcolor(data, cmap=cm.YlOrBr)
        xLabels = (np.linspace(1,n,n,dtype=int))
        yLabels = (np.linspace(1,n,n,dtype=int))
        xpos    = np.linspace(1,n,n)-0.5
        ypos    = np.linspace(1,n,n)-0.5
    
        for y in range(n):
            for x in range(n):
                s = str(round(data[y, x], precis))  # added s for plt.txt and reverse x and y for data addressing
                plt.text(x + 0.5, y + 0.5, s,
                    horizontalalignment='center',
                    verticalalignment='center',
                    )
    
        plt.colorbar(heatmap, format=f'%.{precis}f')  # add precis to the colorbar
        plt.xticks(xpos,xLabels)
        plt.yticks(ypos,yLabels)
        plt.title(f'{title}')
        fig.savefig(f'{pathOut}/{fileName}.pdf', format='pdf')  # this should be before plt.show()
        if (show == False ):
            plt.close(fig)        
        elif (show == True):        
            plt.show()
    
    
    # the function expects an array, not a list
    data = np.array([ 0.00662896, -0.00213044, -0.00156812,  0.01450994, -0.00875174, -0.01561342, -0.00694762,  0.00476027,  0.00470659])
    
    # function call
    plot_heatmap('.', 'test', data, 'test', 4, True)
    

    【讨论】:

    • 感谢您的两个解决方案和提示。使用 round 函数,我们对 2 位小数的表示法有一点问题,结果只有一位小数,因为值接近于零,我们也因为同样的原因丢失了有关信号的信息。我发现了一个额外的事情是在heatmap = plt.pcolor(data, cmap=cm.YlOrBr, norm=mpl.colors.Normalize(vmin=np.amin(data)*1.5, vmax=np.amax(data)*1.5)) 中定义限制。添加限制 f 字符串可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    相关资源
    最近更新 更多