【问题标题】:How to customize the location of color bar in Seaborn heatmap?如何在 Seaborn 热图中自定义颜色条的位置?
【发布时间】:2021-09-16 21:47:42
【问题描述】:

我有以下代码来创建热图。但是,它会创建颜色条和右轴文本的重叠。文字没有问题,我希望它是这样的长度。

如何在热图的右侧/左侧找到没有重叠的颜色栏? 我尝试在 cbar_kws 中使用“pad”参数,但没有帮助。enter image description here

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

PT=pd.DataFrame(np.random.randn(300,3), columns=list('ABC'))
miniPT=PT.iloc[:,:-1]
SMALL_SIZE = 8
MEDIUM_SIZE = 80
BIGGER_SIZE = 120    
plt.rc('font', size=MEDIUM_SIZE)          # controls default text sizes
plt.rc('axes', titlesize=MEDIUM_SIZE)     # fontsize of the axes title
plt.rc('axes', labelsize=MEDIUM_SIZE)    # fontsize of the x and y labels
plt.rc('xtick', labelsize=MEDIUM_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('legend', fontsize=MEDIUM_SIZE)    # legend fontsize
plt.rc('figure', titlesize=BIGGER_SIZE)  # fontsize of the figure title
plt.figure(figsize=(10, miniPT.shape[0]/5.2))
ax =sns.heatmap(miniPT, annot=False, cmap='RdYlGn')
for _, spine in ax.spines.items():
    spine.set_visible(True)
# second axis
asset_list=np.asarray(PT['C'])
asset_list=asset_list[::-1]
ax3 = ax.twinx()
ax3.set_ylim([0,ax.get_ylim()[1]])
ax3.set_yticks(ax.get_yticks())
ax3.set_yticklabels(asset_list, fontsize=MEDIUM_SIZE*0.6)
# colorbar
cbar = ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=MEDIUM_SIZE)

【问题讨论】:

    标签: python seaborn visualization heatmap


    【解决方案1】:

    让 matplotlib 自动调整重叠的一种方法是显式创建子图:一个用于热图,另一个用于颜色条。 sns.heatmapcbar_ax= 参数可以设置为指向这个子图。需要gridspec_kws= 来设置相对大小。最后,plt.tight_layout() 将调整所有的内边距,使一切都很好。

    问题的代码包含一些奇怪的设置(例如,字体大小为 80 是巨大的)。此外,300 行将不可避免地导致文本重叠(字体大小需要非常小,以使非重叠文本无法阅读)。下面是一些更简化的示例代码:

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    PT = pd.DataFrame(np.random.randn(100, 3), columns=list('ABC'))
    fig, (ax, cbar_ax) = plt.subplots(ncols=2, figsize=(10, len(PT) / 5.2), gridspec_kw={'width_ratios': [10, 1]})
    sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=cbar_ax, ax=ax)
    for _, spine in ax.spines.items():
        spine.set_visible(True)
    # second axis
    asset_list = np.asarray(PT['C'])
    ax3 = ax.twinx()
    ax3.set_ylim(ax.get_ylim())
    ax3.set_yticks(np.arange(len(PT)))
    ax3.set_yticklabels(asset_list, fontsize=80)
    # colorbar
    cbar_ax.tick_params(labelsize=80)
    plt.tight_layout()
    plt.show()
    

    由于剧情比较大,这里只贴底部,附上完整剧情的链接。

    这就是它的样子:

    • fontsize 80(请注意,字体大小以“每英寸点数”为单位,标准为每英寸 72 点);
    • 图形宽度为 20 英寸(而不是 10);
    • 300 行
    
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    PT = pd.DataFrame(np.random.randn(300, 3), columns=list('ABC'))
    fig, (ax, cbar_ax) = plt.subplots(ncols=2, figsize=(20, len(PT) / 5.2), gridspec_kw={'width_ratios': [15, 1]})
    sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=cbar_ax, ax=ax)
    for _, spine in ax.spines.items():
        spine.set_visible(True)
    # second axis
    asset_list = np.asarray(PT['C'])
    ax3 = ax.twinx()
    ax3.set_ylim(ax.get_ylim())
    ax3.set_yticks(np.arange(len(PT)))
    ax3.set_yticklabels(asset_list, fontsize=80)
    # colorbar
    cbar_ax.tick_params(labelsize=80)
    plt.tight_layout()
    plt.show()
    

    【讨论】:

    • 您好 JohanC,感谢您的建议。但是,它没有帮助,因为我需要一个专门针对我的设置的解决方案:我需要热图中的 300 行,以及 80 的文本大小。重叠文本也没有问题。我想要的只是移动颜色条,这样就不会与文本重叠。我很高兴得到任何其他解决方案:)
    • 嗯,你问的是不可能的。这个字体大小为 80 的文本比 10 英寸的可用宽度更宽。你可以画一个更宽的情节,但仍然会有极端的重叠。
    • 把颜色条放在热图的左边怎么样?可能吗? (再次,保持 300 行)
    • 您可以通过fig, (cbar_ax, ax) = plt.subplots(ncols=2, figsize=..., gridspec_kw={'width_ratios': [1, 15]})设置左侧的颜色条。但这样一来,空间就会被占用。您仍然无法将所有字体大小为 80 的文本放入 10 英寸。
    【解决方案2】:

    我的解决方案最终将颜色条移到左侧。这是代码和输出:

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    PT = pd.DataFrame(np.random.randn(300, 3), columns=list('ABC'))
    fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, len(PT) / 5.2), gridspec_kw={'width_ratios': [15, 15]})
    sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=ax0, ax=ax1)
    for _, spine in ax1.spines.items():
        spine.set_visible(True)
    # second axis
    asset_list = np.asarray(PT['C'])
    ax3 = ax1.twinx()
    ax3.set_ylim(ax1.get_ylim())
    ax3.set_yticks(np.arange(len(PT)))
    ax3.set_yticklabels(asset_list, fontsize=80)
    # colorbar
    ax0.tick_params(labelsize=80)
    plt.tight_layout()
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 2021-07-06
      • 2020-06-21
      • 1970-01-01
      • 2020-10-21
      • 2018-07-13
      • 2018-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多