scipy.stats.ttest_1samp的基于置换的替代方法

q9yhzks0  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(202)

我想使用基于置换的scipy.stats.ttest_1samp替代方法来测试我的观测值的均值是否显著大于零。我偶然发现了scipy.stats.permutation_test,但我不确定它是否也能用于我的情况。我还偶然发现了mne.stats.permutation_t_test,它似乎能满足我的要求,但如果可以的话,我想坚持使用scipy
示例:

import numpy as np
from scipy import stats

# create data

np.random.seed(42)
rvs = np.random.normal(loc=5,scale=5,size=100)

# compute one-sample t-test

t,p = stats.ttest_1samp(rvs,popmean=0,alternative='greater')
vwkv1x7d

vwkv1x7d1#

此检验可以使用permutation_test执行。使用permutation_type='samples',它会“置换”观察值的符号。假设数据已按上述方式生成,则检验可以按如下方式执行:

from scipy import stats
def t_statistic(x, axis=-1):
    return stats.ttest_1samp(x, popmean=0, axis=axis).statistic

res = stats.permutation_test((rvs,), t_statistic, permutation_type='samples')
print(res.pvalue)

如果您只关心p值,则可以使用np.mean代替t_statistic作为统计量来获得相同的结果。
不可否认,只有一个示例的permutation_type='samples'的这种行为在文档中有一点隐藏。
因此,如果数据仅包含一个样本,则通过独立地改变每个观测的符号来形成零分布。
但是,产生相同p值的检验也可以作为双样本检验来执行,其中第二个样本是数据的负数。为了避免特殊情况,这实际上是permutation_test在幕后所做的。
在本例中,上面的示例代码比permutation_test快得多。不过,我将尝试在SciPy 1.10中改进这一点。

8yparm6h

8yparm6h2#

基于当前的docs,使用permutation_test函数似乎无法实现单样本t检验的等效性。但是可以使用numpy实现它,如下所示。这基于R实现(发现here)和this线程已交叉验证,可选择进行单侧检验和针对特定平均值的检验。

import numpy as np

def permutation_ttest_1samp(
    data, popmean, n_resamples, alternative='two-sided', random_state=None
):

    assert alternative in ('two-sided', 'less', 'greater'), (
        "Unrecognized alternative hypothesis"
    )

    n = len(data)

    data = np.asarray(data) - popmean
    dbar = np.mean(data)

    absx = np.abs(data)
    z = []

    rng = np.random.RandomState(random_state)

    for _ in range(n_resamples):
        mn = rng.choice((-1,1), n, replace=True)
        xbardash = np.mean(mn * absx)
        z.append(xbardash)
    z = np.array(z)

    if alternative == 'greater':
        return 1 - (np.sum(z <= -np.abs(dbar)) / n_resamples)
    elif alternative == 'less':
        return np.sum(z <= -np.abs(dbar)) / n_resamples
    return (
        (np.sum(z >= np.abs(dbar)) + np.sum(z <= -np.abs(dbar))) / n_resamples
    )

示例1(针对平均值0的零假设的双侧检验):

rng = np.random.RandomState(42)
rvs = rng.normal(loc=0, scale=0.01, size=1000)

pval = permutation_ttest_1samp(rvs, 0, 100_000, alternative='two-sided', random_state=42)
print(pval)

# 0.53206

与参数化t检验比较:

from scipy.stats import ttest_1samp

stat, pval = ttest_1samp(rvs, popmean=0, alternative='two-sided')
print(pval)

# 0.5325672436623021

示例2(针对非0均值零假设的单侧检验)

rng = np.random.RandomState(42)
rvs = rng.normal(loc=0, scale=3, size=1000)

pval = permutation_ttest_1samp(rvs, 0.1, 100_000, alternative='greater', random_state=42)
print(pval)

# 0.6731

与参数化t检验比较:

from scipy.stats import ttest_1samp

stat, pval = ttest_1samp(rvs, popmean=0.1, alternative='greater')
print(pval)

# 0.6743729530216749

相关问题