如何绘制仅含红、蓝两色的行内对比热力图?
实现双色对比热力图方案
核心思路
针对每行(职业)内同一国家的F/M数值对比,生成标记矩阵标记高值(红)和低值(蓝),再用自定义双色映射绘制热力图。
完整代码
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap # 构建数据集(匹配你的原始数据结构) df = pd.DataFrame({ '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] }) # 数据重塑(修正原代码列名大小写匹配问题) 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') # 生成颜色标记矩阵:1代表高值(红),0代表低值(蓝) color_mask = heatmap_data.copy() for country in heatmap_data.columns.get_level_values('Country').unique(): f_col = (country, 'F') m_col = (country, 'M') # 标记F高于M的单元格为1 color_mask[f_col] = np.where(heatmap_data[f_col] > heatmap_data[m_col], 1, 0) # 标记M高于F的单元格为1 color_mask[m_col] = np.where(heatmap_data[m_col] > heatmap_data[f_col], 1, 0) # 若需处理数值相等的情况,可添加else分支,比如设为0.5对应第三种颜色 # 自定义双色配色方案:蓝色(低值)、红色(高值) cmap = ListedColormap(['#1f77b4', '#ff4b5c']) # 绘制热力图 plt.figure(figsize=(10, 8)) # 用color_mask映射颜色,annot显示原始数值,关闭颜色条(仅两种颜色无需渐变提示) sns.heatmap(color_mask, cmap=cmap, annot=heatmap_data, fmt=".0f", linewidths=.5, cbar=False) plt.xlabel('Country and Gender') plt.ylabel('Profession') plt.xticks(rotation=45) plt.tight_layout() plt.savefig('heatmap.png') plt.show()
关键说明
- 列名匹配:原数据集列名为
profession(小写),需确保pd.melt的id_vars参数与之对应,避免报错。 - 颜色标记逻辑:遍历每个国家,逐行对比F/M数值,将高值单元格标记为1(对应红色),低值标记为0(对应蓝色);若需处理数值相等的场景,可添加额外分支定义第三种颜色。
- 自定义配色:使用
ListedColormap创建仅包含蓝、红两种颜色的配色方案,确保颜色对比清晰。 - 热力图参数:通过
annot=heatmap_data显示原始数值,关闭颜色条(cbar=False)避免混淆。
内容的提问来源于stack exchange,提问作者x89
相关产品推荐
相关产品推荐

