仅使用 2 种颜色创建热图

问题描述 投票:0回答:1

我有一个如下所示的数据集:

profession     Australia_F   Australia_M      Canada_F      Canada_M    Kenya_F   Kenya_M
Author         20            80               55            34          60        23
Librarian      10            34               89            33          89        12
Pilot          78            12               67            90          12        55

我想用这些值绘制一种热图。我试过这个:

melted_df = pd.melt(df, id_vars='Profession', var_name='Country_Gender', value_name='Number')



melted_df[['Country', 'Gender']] = melted_df['Country_Gender'].str.split('_', expand=True)
melted_df['Number'] = pd.to_numeric(melted_df['Number'], errors='coerce')

heatmap_data = melted_df.pivot_table(index='Profession', columns=['Country', 'Gender'], values='Number')

plt.figure(figsize=(10, 8))  
sns.heatmap(heatmap_data, cmap='coolwarm', annot=True, fmt=".1f", linewidths=.5)
plt.xlabel('Country and Gender')  
plt.ylabel('Profession')  
plt.xticks(rotation=45)  
plt.tight_layout()  
plt.savefig('heatmap.png')

它似乎有效,但目前它根据数值为所有单元格分配不同的颜色。但是,我的图表中只需要 2 种颜色:红色和蓝色。

我想要的是,对于每个职业(每行),我比较每个国家/地区的 F 与 M 值,并将较高值的单元格涂成红色。

例如,对于作者,这三个单元格应该是红色的:

澳大利亚_M (80) 加拿大_F (55) 肯尼亚_F (60)

而该行中的其他 3 个应该是蓝色的。我怎样才能实现这个目标?

python pandas matplotlib seaborn heatmap
1个回答
0
投票

您可以使用两个不同的数据框进行着色和文本注释。创建原始数据帧的副本,比较偶数列和奇数列创建布尔值数据帧。这些布尔值(

0
的内部值
False
1
的内部值
True
)然后决定颜色。

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

data = {'Profession': ['Author', 'Librarian', 'Pilot'],
        'Australia_F': [20, 10, 78],
        'Australia_M': [80, 34, 12],
        'Canada_F': [55, 89, 67],
        'Canada_M': [34, 33, 90],
        'Kenya_F': [60, 89, 12],
        'Kenya_M': [23, 12, 55]}
df = pd.DataFrame(data).set_index('Profession')
df_coloring = df.copy()
for colF, colM in zip(df_coloring.columns[::2], df_coloring.columns[1::2]):
    df_coloring[colF] = df[colF] > df[colM]
    df_coloring[colM] = df[colM] > df[colF]

sns.set_style('white')
plt.figure(figsize=(10, 8))
sns.heatmap(df_coloring, cmap='coolwarm', annot=df, fmt=".1f", linewidths=.5, cbar=False)
plt.xlabel('Country and Gender')
plt.ylabel('Profession')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

sns.heatmap with two colors

© www.soinside.com 2019 - 2024. All rights reserved.