【问题标题】:How to create a heat-map with multiple colormaps?如何创建具有多个颜色图的热图?
【发布时间】:2020-07-17 01:58:34
【问题描述】:

如下图所示,我正在寻找一种将两个或多个热图组合成一个的简单方法,即具有多个颜色图的热图。

这个想法是将每个单元格分成多个子单元格。我找不到任何已经实现了这种可视化功能的 python 库。有人知道(至少)这方面的事情吗?

【问题讨论】:

    标签: python matplotlib seaborn visualization


    【解决方案1】:

    您可以重组您的数组以在实际数据之间留出空列,然后创建一个掩码数组以绘制具有透明度的热图。这是添加空列的一种方法(可能不是最好的):

    arr1 = np.arange(20).reshape(4, 5)
    arr2 = np.arange(20, 0, -1).reshape(4, 5)
    filler = np.nan * np.zeros((4, 5))
    
    c1 = np.vstack([arr1, filler]).T.reshape(10, 4).T
    c2 = np.vstack([filler, arr2]).T.reshape(10, 4).T
    c1 = np.ma.masked_array(c1, np.isnan(c1))
    c2 = np.ma.masked_array(c2, np.isnan(c2))
    
    plt.pcolormesh(c1, cmap='bone')
    plt.pcolormesh(c2, cmap='jet')
    

    您还可以使用np.repeat 并将每隔一列屏蔽为@JohanC 注释

    c1 = np.ma.masked_array(np.repeat(arr1, 2, axis=1), np.tile([True, False], arr1.size))
    c2 = np.ma.masked_array(np.repeat(arr2, 2, axis=1), np.tile([False, True], arr2.size))
    

    【讨论】:

    • 为了让它稍微短一点(并且快一点):c1 = np.ma.masked_array(np.repeat(arr1, 2, axis=1), np.tile([True,False], arr1.size))
    【解决方案2】:

    热图可以逐列绘制。白色网格线可以标记单元格边界。

    import numpy as np
    from matplotlib import pyplot as plt
    
    a = np.random.random((5, 6))
    b = np.random.random((5, 6))
    vmina = a.min()
    vminb = b.min()
    vmaxa = a.max()
    vmaxb = b.max()
    
    fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(10,3), gridspec_kw={'width_ratios':[1,1,2]})
    
    ax1.imshow(a, cmap='Reds', interpolation='nearest', origin='lower', vmin=vmina, vmax=vmaxa)
    ax1.set_xticks(np.arange(.5, a.shape[1]-1, 1), minor=True)
    ax1.set_yticks(np.arange(.5, a.shape[0]-1, 1), minor=True)
    
    ax2.imshow(b, cmap='Blues', interpolation='nearest', origin='lower', vmin=vminb, vmax=vmaxb)
    ax2.set_xticks(np.arange(.5, a.shape[1]-1, 1), minor=True)
    ax2.set_yticks(np.arange(.5, a.shape[0]-1, 1), minor=True)
    
    for i in range(a.shape[1]):
        ax3.imshow(a[:,i:i+1], extent=[2*i-0.5, 2*i+0.5, -0.5, a.shape[0]-0.5 ],
                   cmap='Reds', interpolation='nearest', origin='lower', vmin=vmina, vmax=vmaxa)
        ax3.imshow(b[:,i:i+1], extent=[2*i+0.5, 2*i+1.5, -0.5, a.shape[0]-0.5 ],
                   cmap='Blues', interpolation='nearest', origin='lower', vmin=vminb, vmax=vmaxb)
    ax3.set_xlim(-0.5, 2*a.shape[1] -0.5 )
    ax3.set_xticks(np.arange(1.5, 2*a.shape[1]-1, 2), minor=True)
    ax3.set_yticks(np.arange(.5, a.shape[0]-1, 1), minor=True)
    
    for ax in (ax1, ax2, ax3):
        ax.grid(color='white', which='minor', lw=2)
        ax.set_xticks([])
        ax.set_yticks([])
        ax.tick_params(axis='both', which='both', size=0)
    
    plt.show()
    

    PS:如果简洁是一个重要因素,那么所有的装饰、细节和比较都可以省略:

    # import numpy as np
    # from matplotlib import pyplot as plt
    
    a = np.random.random((5, 6))
    b = np.random.random((5, 6))
    norma = plt.Normalize(vmin=a.min(), vmax=a.max())
    normb = plt.Normalize(vmin=b.min(), vmax=b.max())
    
    for i in range(a.shape[1]):
        plt.imshow(a[:, i:i + 1], extent=[2*i-0.5, 2*i+0.5, -0.5, a.shape[0]-0.5], cmap='Reds', norm=norma)
        plt.imshow(b[:, i:i + 1], extent=[2*i+0.5, 2*i+1.5, -0.5, a.shape[0]-0.5], cmap='Blues', norm=normb)
    plt.xlim(-0.5, 2*a.shape[1]-0.5)
    # plt.show()
    

    【讨论】:

      猜你喜欢
      • 2021-06-23
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 1970-01-01
      • 2020-07-28
      • 1970-01-01
      相关资源
      最近更新 更多