首页 > 解决方案 > 如何结合配对图和三角形热图?

问题描述

我正在尝试制作一个上三角相关矩阵,理想情况下我想将其叠加到下三角矩阵的另一张图片上。因此,我希望将遮罩颜色设置为无或透明(否则,如果它是白色的,我将无法叠加)......关于如何在 seaborn 中执行此操作的任何想法?

这是我要修改的图

编辑

这是我想做的事情:使用数据框中的一组列,我想绘制这些列的对图(下三角形)和相关图(上三角形)

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


rs = np.random.RandomState(112358)
d1 = pd.DataFrame(data=rs.normal(size=(100, 10)), columns=[*'abcdefghij' ])

corr1 = d1.corr()
mask1 = np.tril(np.ones_like(corr1, dtype=bool))

fig, ax = plt.subplots(figsize=(11, 9))

sns.heatmap(corr1, mask=mask1, cmap='PRGn', vmax=.3, vmin=-.3,
            square=True, linewidths=.5, cbar_kws={"shrink": .85, "pad":-.01}, ax=ax)

def hide_current_axis(*args, **kwds):
    plt.gca().set_visible(False)

e = sns.pairplot(d1)

e.map_upper(hide_current_axis)

plt.show()

这段代码当然有效,但它分别绘制了这两个数字。

标签: pythonmatplotlibseaborn

解决方案


创建三角形热图的正常方法是掩盖不需要的部分。那里不会绘制任何内容,原始背景颜色将保持可见。如果您绘制第二张热图,它也只会在未被遮盖的地方绘制。

这是一些代码来演示这个想法。

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

sns.set_theme(style="white")

rs = np.random.RandomState(112358)
d1 = pd.DataFrame(data=rs.normal(size=(100, 10)), columns=[*'abcdefghij' ])
d2 = pd.DataFrame(data=rs.normal(size=(100, 10)), columns=[*'abcdefghij' ])

corr1 = d1.corr()
corr2 = d2.corr()
mask1 = np.tril(np.ones_like(corr1, dtype=bool))
mask2 = np.triu(np.ones_like(corr2, dtype=bool))

fig, ax = plt.subplots(figsize=(11, 9))

sns.heatmap(corr1, mask=mask1, cmap='PRGn', vmax=.3, vmin=-.3,
            square=True, linewidths=.5, cbar_kws={"shrink": .85, "pad":-.01}, ax=ax)
sns.heatmap(corr1, mask=mask2, cmap='RdYlBu', vmax=.3, vmin=-.3,
            square=True, linewidths=.5, cbar_kws={"shrink": .85}, ax=ax)

# the following lines color and hatch the axes background, only the diagonals are visible
ax.patch.set_facecolor('grey')
ax.patch.set_edgecolor('yellow')
ax.patch.set_hatch('xx')

plt.show()

示例图

关于新问题,将配对图与三角形热图相结合。由于 pairplot 是一个图形级别的函数,它会创建自己的带有子图的图形。应该首先创建它。

作为第二步,ax可以使用pairplot 的子图的位置创建一个特殊的热图。将其 facecolor 设置为 'none' 使其完全透明(默认为白色,隐藏所有内容)。

添加颜色条可能更麻烦,因为配对图并没有留下一个很好的位置来定位它。

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

def hide_current_axis(*args, **kwds):
    plt.gca().set_visible(False)

rs = np.random.RandomState(112358)
d1 = pd.DataFrame(data=rs.normal(size=(20, 5)), columns=[*'abcde'])

e = sns.pairplot(d1)
e.map_upper(hide_current_axis)

(xmin, _), (_, ymax) = e.axes[0, 0].get_position().get_points()
(_, ymin), (xmax, _) = e.axes[-1, -1].get_position().get_points()

ax = e.fig.add_axes([xmin, ymin, xmax - xmin, ymax - ymin], facecolor='none')

corr1 = d1.corr()
mask1 = np.tril(np.ones_like(corr1, dtype=bool))
sns.heatmap(corr1, mask=mask1, cmap='seismic', vmax=.5, vmin=-.5,
            linewidths=.5, cbar=False, annot=True, annot_kws={'size': 22}, ax=ax)
ax.set_xticks([])
ax.set_yticks([])
# ax.xaxis.tick_top()
# ax.yaxis.tick_right()

plt.show()

结合pairplot和三角形热图

正如评论中提到的,一种更忠实于 seaborn 理念的方法是根据相关性以及数字显示为右上方子图的轴着色。我找不到示例代码,这是我的尝试:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import pearsonr

def corrfunc(x, y, **kwds):
    cmap = kwds['cmap']
    norm = kwds['norm']
    ax = plt.gca()
    ax.tick_params(bottom=False, top=False, left=False, right=False)
    sns.despine(ax=ax, bottom=True, top=True, left=True, right=True)
    r, _ = pearsonr(x, y)
    facecolor = cmap(norm(r))
    ax.set_facecolor(facecolor)
    lightness = (max(facecolor[:3]) + min(facecolor[:3]) ) / 2
    ax.annotate(f"r={r:.2f}", xy=(.5, .5), xycoords=ax.transAxes,
                color='white' if lightness < 0.7 else 'black', size=26, ha='center', va='center')

rs = np.random.RandomState(112358)
d1 = pd.DataFrame(data=rs.normal(size=(20, 5)), columns=[*'abcde'])

g = sns.PairGrid(d1)
g.map_lower(plt.scatter, s=10)
g.map_diag(sns.histplot, kde=False)
g.map_upper(corrfunc, cmap=plt.get_cmap('seismic'), norm=plt.Normalize(vmin=-.5, vmax=.5))
g.fig.subplots_adjust(wspace=0.06, hspace=0.06) # equal spacing in both directions
plt.show()

为右上角的子图着色


推荐阅读