使用Python的Seaborn库绘制带有p值的相关矩阵

5
我有一个由seaborn生成的对角线相关矩阵。我想要屏蔽那些具有大于0.05的p值的内容。
这是我的现有内容:https://imgur.com/ljwj0U2
sns.set(style="white")
corr = result.corr()
print corr

mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True
f, ax = plt.subplots(figsize=(11, 9))
sns_plot = sns.heatmap(result.corr(),mask=mask, annot=True, center=0, square=True, fmt=".1f", linewidths=.5, cmap="Greens")

希望能得到关于这个问题的任何帮助。 非常感谢。


如果a = result.corr(),那么heatmap(a, mask=mask & (a>0.05)) - ImportanceOfBeingErnest
嗨,ImportanceOfBeingErnest.... 这不是我想要的,但实际上更好!所以...我已经遮盖了三角形的上半部分(只显示三角形的下半部分)。你的建议是在一个半三角形中显示所有相关性,并且在另一个半三角形中仅显示p <0.05的相关性!https://imgur.com/a/YziKmGT我要做的唯一修改是将(mask[np.triu_indices_from(mask)])更改为(mask[np.tril_indices_from(mask)])(应用于底部的mask),请注意(a < 0.05)。 - Richard Summers
也许是 mask | (a > 0.05)?由于没有提供最小可复现示例,我无法在此处测试任何内容。 - ImportanceOfBeingErnest
BOOM!啊啊啊,你太棒了!掩码 | (a > 0.05) 这是... 再次感谢。 - Richard Summers
1
抱歉翻出这个,但我正在寻找同样的东西。对于正在寻找过滤sns热力图以获取显著相关性的人们,请注意:这并不过滤p值,因为从统计学解释上来说,.corr()只给出了相关系数,而没有p值(从针对零的统计测试中获得)。 - Björn
1
我认为p值和相关系数r之间存在混淆。 - Björn
1个回答

12
为了完整起见,这里提供了一个解决方案,使用scipy.stats.pearsonr (文档)来创建一个p值矩阵。接下来创建一个布尔掩码,传递给seaborn(或者另外与numpynp.triu结合使用以隐藏相关性的上三角)。
def corr_sig(df=None):
    p_matrix = np.zeros(shape=(df.shape[1],df.shape[1]))
    for col in df.columns:
        for col2 in df.drop(col,axis=1).columns:
            _ , p = stats.pearsonr(df[col],df[col2])
            p_matrix[df.columns.to_list().index(col),df.columns.to_list().index(col2)] = p
    return p_matrix

p_values = corr_sig(df)
mask = np.invert(np.tril(p_values<0.05))
# note seaborn will hide correlation were the boolean value is True in the mask


完整过程及示例

首先创建一些样本数据(3个相关变量;3个不相关的变量):

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

# Simulate 3  correlated variables
num_samples = 100
mu = np.array([5.0, 0.0, 10.0])
# The desired covariance matrix.
r = np.array([
        [  3.40, -2.75, -2.00],
        [ -2.75,  5.50,  1.50],
        [ -2.00,  1.50,  1.25]
    ])
y = np.random.multivariate_normal(mu, r, size=num_samples)
df = pd.DataFrame(y)
df.columns = ["Correlated1","Correlated2","Correlated3"]

# Create two random variables 
for i in range(2):
    df.loc[:,f"Uncorrelated{i}"] = np.random.randint(-2000,2000,len(df))

# To make sure that they are uncorrelated - add also a nearly invariant variables
df.loc[:,"Near Invariant"] = np.random.randint(-99,-95,num_samples)

用于方便的绘图函数
主要用于美化热力图。

def plot_cor_matrix(corr, mask=None):
    f, ax = plt.subplots(figsize=(11, 9))
    sns.heatmap(corr, ax=ax,
                mask=mask,
                # cosmetics
                annot=True, vmin=-1, vmax=1, center=0,
                cmap='coolwarm', linewidths=2, linecolor='black', cbar_kws={'orientation': 'horizontal'})

所有相关性的例子数据的相关性图
为了让您了解在此示例相关矩阵中未过滤显著相关性(p值<0.05)的情况下相关性的外观。

# Plotting without significance filtering
corr = df.corr()
mask = np.triu(corr)
plot_cor_matrix(corr,mask)
plt.show()

enter image description here

只显示显著相关性的示例数据相关图 最终绘制的图仅包含显著性水平小于0.05的相关系数。

# Plotting with significance filter
corr = df.corr()                            # get correlation
p_values = corr_sig(df)                     # get p-Value
mask = np.invert(np.tril(p_values<0.05))    # mask - only get significant corr
plot_cor_matrix(corr,mask)  

在这里输入图像描述

结论

虽然在第一个相关矩阵中有一些相关系数 (r) 大于 0.05 (根据 OP 提问中的评论进行过滤),这并不意味着 p 值是显著的。因此,重要的是区分 p 值和相关系数 r

我希望这个答案将来对其他人寻找使用 sns.heatmap 绘制显著相关性的方法有所帮助。


我遇到了一个 ValueError: Mask must have the same shape as data 的错误。 - prof31
你好,我无法复制您的错误。对我来说,代码仍然可以正常运行。您可能需要提出一个新问题。如果您运行此代码,它应该返回“TRUE”。在我的示例中,相关性数据框和掩码的形状应该是(6,6)。 - Björn
你好, 我收到了以下错误信息: <ipython-input-7-7bc01e37ca24> in corr_sig(df) 4 for col2 in df.drop(col,axis=1).columns: 5 _ , p = stats.pearsonr(df[col],df[col2]) ----> 6 p_matrix[df.columns.to_list().index(col),df.columns.to_list().index(col2)] = p 7 return p_matrix 8 AttributeError: 'Index'对象没有'to_list'属性。 - Alan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接