【问题标题】:Change colour scheme label to log scale without changing the axis in matplotlib将配色方案标签更改为对数刻度而不更改 matplotlib 中的轴
【发布时间】:2021-01-23 09:40:35
【问题描述】:

我对 python 编程很陌生。我有一个使用 matplotlib 绘制热图的脚本。 X 轴值的范围 =(-180 到 +180)和 Y 轴值 =(0 到 180)。二维热图根据 x-y 图中指定区域中出现的点数(由“bin”(见下文)定义)为 Rainbow 中的区域着色。 在这种情况下,x = values_Rot 和 y = values_Tilt(代码见下文)。

到目前为止,此脚本以线性比例为 2D 热图着色。如何更改此脚本,使其以对数刻度为热图着色?请注意,我只想将热图着色方案更改为对数比例,即仅指定区域中的点数。 x 和 y 轴在线性比例(而不是对数比例)中保持不变。 部分代码在这里。

rot_number = get_header_number(headers, AngleRot)
tilt_number = get_header_number(headers, AngleTilt)
psi_number = get_header_number(headers, AnglePsi)

values_Rot = []
values_Tilt = []
values_Psi = []

for line in data:
    try:
        values_Rot.append(float(line.split()[rot_number]))
        values_Tilt.append(float(line.split()[tilt_number]))
        values_Psi.append(float(line.split()[psi_number]))

    except:
        print ('This line didnt work, it may just be a blank space. The line is:' + line)

# Change the values here if you want to plot something else, such as psi. 
# You can also change how the data is binned here.
plt.hist2d(values_Rot, values_Tilt, bins=25,)
plt.colorbar()
plt.show()

plt.savefig('name_of_output.png')

【问题讨论】:

    标签: python matplotlib heatmap


    【解决方案1】:

    您可以使用LogNorm 作为颜色,使用plt.hist2d(...., norm=LogNorm())。这是一个比较。

    要在底数 2 中添加刻度,the developers suggest 将底数添加到 LogLocatorLogFormatter。在这种情况下,LogFormatter 似乎用一位小数 (.0) 写入数字,StrMethodFormatter 可用于显示不带小数的数字。根据数字的范围,有时次要刻度(较短的标记线)也会得到一个字符串,可以通过为次要颜色条刻度分配 NullFormatter 来抑制它。

    请注意,base 2 和 base 10 定义完全相同的颜色转换。刻度的位置和标签是不同的。下面的示例创建了两个颜色条来展示不同的外观。

    import matplotlib.pyplot as plt
    from matplotlib.ticker import NullFormatter, StrMethodFormatter, LogLocator
    from matplotlib.colors import LogNorm
    import numpy as np
    from copy import copy
    
    # create some toy data for a standalone example
    values_Rot = np.random.randn(100, 10).cumsum(axis=1).ravel()
    values_Tilt = np.random.randn(100, 10).cumsum(axis=1).ravel()
    
    fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(15, 4))
    
    cmap = copy(plt.get_cmap('hot'))
    cmap.set_bad(cmap(0))
    
    _, _, _, img1 = ax1.hist2d(values_Rot, values_Tilt, bins=40, cmap='hot')
    ax1.set_title('Linear norm for the colors')
    fig.colorbar(img1, ax=ax1)
    _, _, _, img2 = ax2.hist2d(values_Rot, values_Tilt, bins=40, cmap=cmap, norm=LogNorm())
    ax2.set_title('Logarithmic norm for the colors')
    fig.colorbar(img2, ax=ax2)  # default log 10 colorbar
    cbar2 = fig.colorbar(img2, ax=ax2)  # log 2 colorbar
    cbar2.ax.yaxis.set_major_locator(LogLocator(base=2))
    cbar2.ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.0f}'))
    cbar2.ax.yaxis.set_minor_formatter(NullFormatter())
    plt.show()
    

    请注意,log(0) 是负无穷大。因此,左侧图中的零值(最深的颜色)在带有对数颜色值的图上留空(白色背景)。如果您只想为这些零使用最低颜色,则需要设置'bad' color。为了不更改标准颜色图,最新的 matplotlib 版本希望您首先制作颜色图的副本。

    PS:当调用plt.savefig() 时,在plt.show() 之前调用它很重要,因为plt.show() 清除了情节。

    此外,请尽量避免使用“喷射”颜色图,因为它有一个不是极端的亮黄色区域。它可能看起来不错,但可能非常具有误导性。 This blog article 包含详尽的解释。 The matplotlib documentation 包含可用颜色图的概述。

    请注意,要比较两个图,需要使用plt.subplots(),而不是plt.hist2d,需要ax.hist2d(请参阅this post)。此外,对于两个颜色条,颜色条所基于的元素需要作为参数给出。您的代码的最小更改如下所示:

    from matplotlib.ticker import NullFormatter, StrMethodFormatter, LogLocator
    from matplotlib.colors import LogNorm
    from matplotlib import pyplot as plt
    from copy import copy
    
    # ...
    # reading the data as before
    
    cmap = copy(plt.get_cmap('magma'))
    cmap.set_bad(cmap(0))
    plt.hist2d(values_Rot, values_Tilt, bins=25, cmap=cmap, norm=LogNorm())
    cbar = plt.colorbar()
    cbar.ax.yaxis.set_major_locator(LogLocator(base=2))
    cbar.ax.yaxis.set_major_formatter(StrMethodFormatter('{x:.0f}'))
    cbar.ax.yaxis.set_minor_formatter(NullFormatter())
    
    plt.savefig('name_of_output.png') # needs to be called prior to plt.show()
    plt.show()
    

    【讨论】:

    • 谢谢 - 有没有办法将日志的基数从 base10 更改为 base 2?
    • 感谢您提供有用的反馈。您的回答确实部分回答了这个问题,但是您如何在不大量修改我的原始代码的情况下从基数 10 更改为基数 2。由于特定原因,我需要更改基数 - 我只有 (0-9) 的数字,这是我的热图上的范围。
    • 我用代码所需的最小更改更新了答案。不要忘记将“jet”更改为不那么繁琐的颜色图。我还更改了样本值,使其具有带有小数字的颜色条。
    猜你喜欢
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多