python - 按列具有多个颜色图的热图
问题描述
我有一个数据框,其中每列包含被认为是“正常”的值,如果它们落在一个区间内,每列都不同:
# The main df
df = pd.DataFrame({"A": [20, 10, 7, 39],
"B": [1, 8, 12, 9],
"C": [780, 800, 1200, 250]})
表示的df_info
每一列的间隔df
。因此,例如df_info["A"][0]
是列的最小值df["A"]
,df_info["A"][1]
代表列的最大值,df["A"]
依此类推。
df_info = pd.DataFrame({"A": [22, 35],
"B": [5, 10],
"C": [850, 900]})
感谢这个SO Answer,我能够创建一个自定义热图,以低于范围的蓝色值、高于范围的红色值和范围内的白色值打印。请记住,每一列都有不同的范围。所以我根据这个标准化:
df_norm = pd.DataFrame()
for col in df:
col_min = df_info[col][0]
col_max = df_info[col][1]
df_norm[col] = (df[col] - col_min) / (col_max - col_min)
最后打印了我的热图
vmin = df_norm.min().min()
vmax = df_norm.max().max()
norm_zero = (0 - vmin) / (vmax - vmin)
norm_one = (1 - vmin) / (vmax - vmin)
colors = [[0, 'darkblue'],
[norm_zero, 'white'],
[norm_one, 'white'],
[1, 'darkred']
]
cmap = LinearSegmentedColormap.from_list('', colors, )
fig, ax = plt.subplots()
ax=sns.heatmap(data=data,
annot=True,
annot_kws={'size': 'large'},
mask=None,
cmap=cmap,
vmin=vmin,
vmax=vmax) \
.set_facecolor('white')
在示例中,您可以看到第三列的值与0-1
间隔(和第一列)相比要高/低得多,因此它们“吸收”了所有红色和蓝色的阴影。
问题:我想要获得的是对每列使用整个红色/蓝色阴影,或者至少减少(例如)第一列和第三列之间的感知差异。
我很难:
- 创建一个自定义颜色图,其中每个颜色图规范化按列执行
- 使用多个颜色图,每个颜色图应用于不同的列
- 应用颜色图
mpl.colors.LogNorm
,但我不确定如何将它与我的自定义一起使用LinearSegmentedColormap
解决方案
使用每列的掩码,您可以每列绘制热图列,每个列都有自己的颜色图:
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.cm import ScalarMappable
df = pd.DataFrame({"A": [20, 10, 7, 39],
"B": [1, 8, 12, 9],
"C": [780, 800, 1200, 250]})
df_info = pd.DataFrame({"A": [22, 35],
"B": [5, 10],
"C": [850, 900]})
df_norm = pd.DataFrame()
for col in df:
col_min = df_info[col][0]
col_max = df_info[col][1]
df_norm[col] = (df[col] - col_min) / (col_max - col_min)
fig, ax = plt.subplots()
for col in df:
vmin = df_norm[col].min()
vmax = df_norm[col].max()
norm_zero = (0 - vmin) / (vmax - vmin)
norm_one = (1 - vmin) / (vmax - vmin)
colors = [[0, 'darkblue'],
[norm_zero, 'white'],
[norm_one, 'white'],
[1, 'darkred']]
cmap = LinearSegmentedColormap.from_list('', colors)
mask = df.copy()
for col_m in mask:
mask[col_m] = col != col_m
sns.heatmap(data=df_norm,
annot=df.to_numpy(), annot_kws={'size': 'large'}, fmt="g",
mask=mask,
cmap=cmap, vmin=vmin, vmax=vmax, cbar=False, ax=ax)
ax.set_facecolor('white')
colors = [[0, 'darkblue'],
[1 / 3, 'white'],
[2 / 3, 'white'],
[1, 'darkred']]
cmap = LinearSegmentedColormap.from_list('', colors)
cbar = plt.colorbar(ScalarMappable(cmap=cmap), ax=ax, ticks=[0, 1 / 3, 2 / 3, 1])
cbar.ax.yaxis.set_ticklabels(['min\nlimit', 'min', 'max', 'max\nlimit'])
plt.tight_layout()
plt.show()
推荐阅读
- ios - 如何在 SwiftUI 列表中保持相等的行距?
- java - Java - 仅使用一个注释验证多个字段
- mysql - 在没有CASE的SQL中嵌套NULLIF(将列的值分配给null if(条件A)或(条件B))
- iframe - Apache superset iFrame 集成具有 CORS,无法正常工作
- python - rpi-rf_send 脚本 + python raspberry pi 中的硬编码射频代码
- go - 尝试“获取”geos 包时出错
- postgresql - 如何为在模式中有关系的graphql进行突变
- html - 将引导程序用于 wordpress 主题时,我的自定义 css 不起作用
- spring-boot-jpa - 使用 JPA 的 Spring Boot
- delphi - TPanel - 是否实施了 BevelXXXX 值 bvSpace?