【问题标题】:Seaborn Heatmap Color By RowSeaborn 热图颜色(按行)
【发布时间】:2020-02-20 17:45:18
【问题描述】:

我有一个网络图。

每个节点都是一个案例,每个边都是一个 CPT。

我使用community.best_partition 将图表分成四个社区(用颜色表示)。

为了更好地可视化每个社区中的共享 CPT 和案例数量,我使用 plt.subplotssns.heatmap 创建了四个社区之间具有相似匹配颜色的热图。

生成热图的代码:

fig, axs = plt.subplots(nrows=4, figsize=(16,8), sharex=True)

cmaps = ['Blues', 'Oranges', 'Greens', 'Reds']

comms = range(4)

for ax, cmap, comm in zip(axs, cmaps, comms):
    sns.heatmap(
        data=_.loc[[comm]],
        ax=ax,
        cmap=cmap,
        annot=True,
        annot_kws={
            'fontsize' : 12
        },
        fmt='g',
        cbar=False,
        robust=True,
    )

    ax.set_ylabel('Community')

    ax.set_xlabel('');

问题

sns.heatmap 中是否有一种方法可以按行(在本例中为社区)指定颜色,而无需创建 4 个单独的热图?

这是一些示例数据:

cpt   52320  52353  52310  49568  50432  52234  52317  50435  52354  52332
comm                                                                      
0       NaN    3.0    NaN    1.0    1.0    NaN    2.0    2.0    NaN    3.0
1       1.0   30.0    NaN    NaN    NaN    1.0    NaN    NaN    NaN   20.0
2       NaN    NaN  160.0    NaN    NaN    NaN    NaN    NaN    NaN    NaN
3       NaN    7.0    NaN    NaN    NaN    NaN    NaN    NaN    1.0   12.0

【问题讨论】:

    标签: python matplotlib seaborn heatmap


    【解决方案1】:

    我认为你不能使用 seaborn 的热图来做到这一点,但你可以使用 imshow() 重新创建输出

    d = """      52320  52353  52310  49568  50432  52234  52317  50435  52354  52332                                                                     
    0       NaN    3.0    NaN    1.0    1.0    NaN    2.0    2.0    NaN    3.0
    1       1.0   30.0    NaN    NaN    NaN    1.0    NaN    NaN    NaN   20.0
    2       NaN    NaN  160.0    NaN    NaN    NaN    NaN    NaN    NaN    NaN
    3       NaN    7.0    NaN    NaN    NaN    NaN    NaN    NaN    1.0   12.0"""
    df = pd.read_csv(StringIO(d), sep='\\s+')
    
    N_communities = df.index.size
    N_cols = df.columns.size
    cmaps = ['Blues', 'Oranges', 'Greens', 'Reds']
    
    fig, ax = plt.subplots()
    
    for i,((idx,row),cmap) in enumerate(zip(df.iterrows(), cmaps)):
        ax.imshow(np.vstack([row.values, row.values]), aspect='auto', extent=[-0.5,N_cols-0.5,i,i+1], cmap=cmap)
        for j,val in enumerate(row.values):
            vmin, vmax = row.agg(['min','max'])
            vmid = (vmax-vmin)/2
            if not np.isnan(val):
                ax.annotate(val, xy=(j,i+0.5), ha='center', va='center', color='black' if (val<=vmid or vmin==vmax) else 'white')
    ax.set_ylim(0,N_communities)
    
    ax.set_xticks(range(N_cols))
    ax.set_xticklabels(df.columns, rotation=90, ha='center')
    
    ax.set_yticks(0.5+np.arange(N_communities))
    ax.set_yticklabels(df.index)
    ax.set_ylabel('Community')
    
    ax.invert_yaxis()
    
    fig.tight_layout()
    

    【讨论】:

    • 注意到社区 2 中的值 160 几乎不可见。预计这是因为样本数据中只有值吗?
    • 没错,如果行上只有一个值(或者如果所有值都相等),则代码不是很健壮。我已经通过额外的测试修改了我的答案,以考虑到这种可能性。
    • 请注意,您可能想使用ax.annotate(f'{val:.0f}', .. 或类似的东西来避免尾随.0。当单元格变得太窄时,可以添加ax.annotate(..., rotation=90)
    猜你喜欢
    • 2018-05-09
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 2018-05-07
    • 2020-12-03
    • 1970-01-01
    • 2015-04-06
    • 2021-04-14
    相关资源
    最近更新 更多