python - 按列显示多个颜色图的热图

标签 python pandas dataframe matplotlib heatmap

我有一个数据框,其中每一列都包含被认为是“正常”的值,如果它们落在一个区间内,每一列都不同:

# 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 的 min ["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')

enter image description here

在示例中,您可以看到第三列的值比 0-1 区间(和第一列)高/低得多,因此它们“吸收”了所有阴影红色和蓝色。

问题: 我想要获得的是为每一列使用整个红色/蓝色阴影,或者至少减少(例如)第一列和第三列之间的感知差异。

我很难:

  1. 创建一个自定义颜色图,其中每个颜色图规范化按列执行
  2. 使用多个颜色图,每个颜色图应用于不同的列
  3. 正在应用颜色图 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()

heatmap in columns

关于python - 按列显示多个颜色图的热图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66822222/

相关文章:

python - 导入错误: no module named 'Adafruit_DHT'

python - 在 WTForms 中访问 RadioField 的子字段

python - Pandas 非常简单 分组总大小的百分比

Python Pandas - 如何检查 DataFrame 中的值

python-3.x - 删除数据框和 csv 文件中的特定字符

python - 自定义内联外键,不重复

python - 持续检查 VPN 连接 - Python

python - 使用多处理时拥有全局变量是否有效?

python - 如何使用pyspark从字符串中提取数字格式

dataframe - 在 Julia 中使用括号与点表示法访问 Dataframe 列