如何判断两个数组是否来自不相关的分布?

问题描述 投票:0回答:1

我有两个数组 -

array1
array2
。我能有多自信地说它们是由不相关的分布生成的?仅检查相关值是不够的;还需要检查相关值。我还需要 p 值。

想到使用以下方法-

import numpy as np
from scipy.stats import pearsonr

array1 = np.array([1, 2, 3, 4, 5])
array2 = np.array([5, 4, 3, 2, 1])

# Calculate the Pearson correlation coefficient and p-value
res = pearsonr(array1, array2, alternative='two-sided')

correlation_coefficient, p_value = res.statistic, res.pvalue

# Print the results
print(f"Pearson Correlation Coefficient: {correlation_coefficient}")
print(f"P-value: {p_value}")

# Define the confidence level (e.g., 95%)
confidence_level = 0.95

# Make a conclusion based on the p-value
if p_value < (1 - confidence_level):
    print(f"I am {confidence_level * 100}% confident that these two arrays are correlated.")

输出-

Pearson Correlation Coefficient: -1.0
P-value: 0.0
I am 95.0% confident that these two arrays are correlated.

然而,这种方法的一个问题是在 docstring 语句中发现的 -

此函数还执行原假设检验 样本背后的分布是不相关的,并且通常 分布式。

我只是想测试样本背后的分布不相关的假设,而不关心分布的性质 - 正态分布或其他任何分布。

有什么替代方案可以解决这个问题吗?


两个暂定解决方案

模拟不相关数组的分布

我可以生成两个随机数组(与

array1
长度相同)并计算它们的相关性。通过重复多次,我可以获得不相关数组之间相关值的分布,而无需引用底层分布类型。我可以使用此分布来获取
array1
array2
之间实际观察到的相关性的 p 值。

当然,

numpy
随机生成器遵循的分布可能会产生影响。此外,如果已经存在解决方案,我想避免这么多编码。

我可以使用
method
scipy.stats.pearsonr
参数吗?

不确定

method
pearsonr
参数的作用是什么。特别是当
method
设置为
PermutationMethod
时。这是否能以某种方式解决我的疑问?

scipy p-value hypothesis-test pearson-correlation numpy-random
1个回答
0
投票

首先计算统计量的观测值:

import numpy as np
from scipy import stats

array1 = np.array([1, 2, 3, 4, 5])
array2 = np.array([5, 4, 3, 2, 1])

# Calculate the observed value of the statistic
res = stats.pearsonr(array1, array2, alternative='two-sided')
observed = res.statistic  # observed value of the statistic 
observed  # -1.0

这看起来相当极端,但我们需要量化由于偶然性而获得这种极值的概率。排列测试可以在不假设数据采样的分布形式的情况下完成此操作。

如果样本来自独立分布,则第二个数组中观察到的任何值都有可能与第一个数组中观察到的任何值配对。因此,排列测试的零假设是所有可能的配对均具有相同的可能性,并且观察到的配对是随机抽样的。通过计算第二个数组的每个排列的统计量。首先,我们获得统计量的零分布。

import itertools
rng = np.random.default_rng(4259845268735019)
null_distribution = []
for resample in itertools.permutations(array2):
    res = stats.pearsonr(array1, resample)
    null_distribution.append(res.statistic)
null_distribution = np.asarray(null_distribution)

与分布依赖于正/负相关的替代方案相对应的(单边)p 值是大于/小于或等于观察到的统计值的零分布的分数。两侧 p 值是两者最小值的两倍。

pvalue_greater = (null_distribution >= observed).sum() / len(null_distribution)
pvalue_less = (null_distribution <= observed).sum() / len(null_distribution)
pvalue = 2 * min(pvalue_greater, pvalue_less)
pvalue  # 0.016666666666666666

零分布恰好关于 0 对称,因此您可能更愿意将双边 p 值视为比统计观测值“更极端”(在任一方向)的统计值的分数。

(abs(null_distribution) >= abs(observed)).sum() / len(null_distribution)
# 0.016666666666666666

这本质上就是当您通过

pearsonr
method='PermutationMethod'
在幕后所做的事情。

res = stats.pearsonr(array1, array2, alternative='two-sided', method=stats.PermutationMethod())
res.pvalue  # 0.016666666666666666

随着数组变大,排列的数量也会快速增长。默认情况下,'PermutationMethod' 进行的重新采样不超过 9999 次,如果不详尽,则选择随机排列。您可以使用

n_resamples
PermutationMethod
参数更改此设置。

考虑避免使用诸如“我有 95.0% 的信心这两个数组相关”之类的陈述,而是报告完整的 p 值以及如何获得它。

© www.soinside.com 2019 - 2024. All rights reserved.