【问题标题】:How to combine a pairplot and a triangular heatmap?如何结合配对图和三角形热图?
【发布时间】:2021-02-08 20:30:03
【问题描述】:

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

编辑

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

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()

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

【问题讨论】:

  • 你有一些代码吗?你在使用seaborn.heatmap 来生成情节吗?

标签: python matplotlib seaborn


【解决方案1】:

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

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

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 是figure-level function,它使用子图创建自己的图形。应该先创建它。

作为第二步,可以使用pairplot 的子图的位置为热图创建一个特殊的ax。将其 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()

如 cmets 中所述,更忠实于 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()

【讨论】:

  • 谢谢!这非常有用......但是,在我的特定应用程序中,我需要在同一个图中绘制一个 seaborn pairplot(下三角形)和一个相关图(上三角形)。 SI有没有办法做到这一点,假设pairplot和map的轴是相同的?
  • pairplot 是图形级别的函数,可能会绘制很多子图。热图仅绘制在一个子图上。你能edit你的问题并添加带有玩具数据和配对图图像的代码吗?
  • 在这种情况下,pairplot 和相关图是在同一组列上计算的。我编辑了我的问题
  • 感觉更容易/不那么繁琐地映射一个自定义函数,该函数设置轴的 facecolor 并添加具有相关系数的文本......我认为有一个答案表明有人在 SO。
  • @mwaskom 这是否更接近您的想法?
【解决方案2】:

有时,根据 abs(r) 更改相关值的大小很有用。更高的值->更大的数字。

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
    tam = int(70*abs(r))
    if tam < 10:
        tam = 10
    ax.annotate(f"{r:.2f}", xy=(.5, .5), xycoords=ax.transAxes,
            color='white' if lightness < 0.7 else 'black', size=tam, ha='center', va='center')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 2019-01-12
    • 2019-01-29
    • 2022-06-10
    • 1970-01-01
    相关资源
    最近更新 更多