如何在Seaborn中对两个不同取值范围做掩码,实现热图指定区间标红
错误原因
- 条件逻辑错误:你需要匹配
2.3e-6 ≤ 数值 ≤ 0.05的区间,原代码写为X.values<2.3e-6 & 0.05<X.values,该条件不可能同时成立,属于逻辑写反。 - 运算符优先级错误:Python中按位与
&的优先级高于比较运算符>/<,不加括号会先执行&运算,导致类型不匹配报错。 - 热图掩码逻辑错误:
sns.heatmap的mask参数规则是值为True的位置会被隐藏,第二层热图只需要显示目标区间的数值,所以掩码要排除非目标区间、以及原本上三角需要隐藏的位置。
修正后代码
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from scipy.stats import pearsonr N = 10 data = np.random.uniform(0, 45, size=(N, N)) for x, y in np.random.randint(0, N, 50).reshape(-1, 2): data[x, y] = np.nan # 随机填充部分空值 df = pd.DataFrame(data) def pearsonr_pval(x,y): return pearsonr(x,y)[1] data = df.loc[:, (df != 0).any(axis=0)] # 测试用例中N=10列数不足,实际运行时可删除下行调整为你的原始逻辑 data = data.iloc[:,3:min(50, data.shape[1])] to_log = data.columns df_log = data[to_log].applymap(lambda x: np.log(x+1)) X = df_log.corr(method = pearsonr_pval) sns.set_style("darkgrid") mask = np.zeros_like(X) mask[np.triu_indices_from(mask)] = True with sns.axes_style("white"): f, ax = plt.subplots(figsize=(20, 20)) # 第一层热图:显示所有数值,用YlGnBu配色 ax = sns.heatmap(X, mask=mask, vmax=1, vmin=0, square=True, cmap="YlGnBu", annot_kws={"size": 1}) # 第二层热图:只显示2.3e-6~0.05区间的数值,用rocket红系配色 # 掩码规则:隐藏【不在目标区间】或【属于上三角需要隐藏】的位置 mask2 = ~((X.values >= 2.3e-6) & (X.values <= 0.05)) | mask.astype(bool) ax = sns.heatmap(X, mask=mask2, vmax=1, vmin=0, square=True, cmap="rocket", annot_kws={"size": 1}, # 关闭第二层的色条,避免重复 cbar=False) plt.show()
补充说明
- 代码中额外添加了第二层热图的
cbar=False参数,避免出现两个重复色条 - 测试用例中生成的10×10矩阵做列切片时可能出现索引越界,已经做了兼容处理,你的实际数据列数足够的话可以改回原逻辑
内容的提问来源于stack exchange,提问作者Noob Programmer
相关产品推荐
相关产品推荐

