Skip to content

单样本t检验 ​

检验一个均值与参照值的差异,或两个均值之间的差异。

计算口径 ​

按研究设计区分独立对象与同一对象的配对测量。小样本应关注相关分布的正态性与离群值;单侧方向应事先提出。

选择待检验变量并输入检验值,例如量表中性点3。差值方向为样本均值减检验值,单侧“大于/小于”也按这个方向解释。

先看差值方向与置信区间,再报告t、自由度、p及效应量。p不显著不等于两者等效。原始输出保留样本和分布诊断。

同源实现 ​

以下片段来自 core/statistical/comparisons.py 的 t_tests,由镜像脚本按语法树提取。共享辅助函数和分发逻辑包含在完整下载包中。

py
def t_tests(data, options, method):
    alpha = number(options, 'alpha', .05, .0001, .25)
    alternative = choice(options, 'alternative', 'two-sided', ('two-sided', 'less', 'greater'))
    rows, details = [], {}
    headers = [Column('variable', _('变量'), 'text')]
    if method == 'stat_t_one_sample':
        selected = columns(data, options.get('variables'))
        numeric = numeric_frame(data, selected)
        test_value = number(options, 'test_value', 0)
        headers += [Column('n', 'N', 'integer'), Column('summary', _('均值±标准差'), 'mean_sd')]
        for name in selected:
            x = enough(numeric[name].dropna(), 2).to_numpy()
            n, sd = len(x), np.std(x, ddof=1)
            if sd <= 0:
                raise ValueError(_('变量“%(name)s”没有有效变异', name=name))
            estimate, se, df = np.mean(x)-test_value, sd/np.sqrt(n), n-1
            outcome = stats.ttest_1samp(x, test_value, alternative=alternative)
            rows.append({'variable': name, 'n': n, 'summary': mean_sd(x), 'difference': estimate,
                         't': outcome.statistic, 'df': df, 'p': outcome.pvalue,
                         'ci': mean_interval(estimate, se, df, alpha, alternative), 'effect': estimate/sd})
        details['test_value'] = test_value
        effect_label = "Cohen's d"
    elif method == 'stat_t_independent':
        selected = columns(data, options.get('variables'))
        group = options.get('group')
        equal = boolean(options, 'equal_variance', False)
        headers += [Column('group_a', _('组1'), 'text'), Column('n_a', 'N', 'integer', _('组1')),
                    Column('a', _('均值±标准差'), 'mean_sd', _('组1')), Column('group_b', _('组2'), 'text'),
                    Column('n_b', 'N', 'integer', _('组2')), Column('b', _('均值±标准差'), 'mean_sd', _('组2'))]
        for name in selected:
            names, samples = grouped_samples(data, name, group)
            if len(samples) != 2:
                raise ValueError(_('独立样本t检验需要恰好两个有效组'))
            a, b = [enough(x, 2) for x in samples]
            na, nb = len(a), len(b)
            va, vb = np.var(a, ddof=1), np.var(b, ddof=1)
            pooled = ((na-1)*va+(nb-1)*vb)/(na+nb-2)
            if pooled <= 0:
                raise ValueError(_('两组都没有组内变异,无法进行t检验'))
            if equal:
                se, df = np.sqrt(pooled*(1/na+1/nb)), na+nb-2
            else:
                se = np.sqrt(va/na+vb/nb)
                df = (va/na+vb/nb)**2/((va/na)**2/(na-1)+(vb/nb)**2/(nb-1))
            estimate = np.mean(a)-np.mean(b)
            outcome = stats.ttest_ind(a, b, equal_var=equal, alternative=alternative)
            levene = stats.levene(a, b)
            details[name] = {'levene': {'statistic': levene.statistic, 'p': levene.pvalue}, 'groups': names}
            rows.append({'variable': name, 'group_a': names[0], 'group_b': names[1], 'n_a': na, 'n_b': nb,
                         'a': mean_sd(a), 'b': mean_sd(b), 'difference': estimate,
                         't': outcome.statistic, 'df': df, 'p': outcome.pvalue,
                         'ci': mean_interval(estimate, se, df, alpha, alternative), 'effect': estimate/np.sqrt(pooled)})
        details['variance_assumption'] = 'equal' if equal else 'Welch'
        effect_label = "Cohen's d"
    else:
        pairs = paired_columns(data, options)
        headers += [Column('n', _('配对数'), 'integer'), Column('a', _('前项均值±标准差'), 'mean_sd'),
                    Column('b', _('后项均值±标准差'), 'mean_sd')]
        for first, second in pairs:
            pair = enough(numeric_frame(data, [first, second]).dropna(), 2)
            a, b = pair[first].values, pair[second].values
            difference = a-b
            sd = np.std(difference, ddof=1)
            if sd <= 0:
                raise ValueError(_('配对差值没有变异,无法进行配对t检验'))
            estimate, se, df = np.mean(difference), sd/np.sqrt(len(pair)), len(pair)-1
            outcome = stats.ttest_rel(a, b, alternative=alternative)
            rows.append({'variable': first+' − '+second, 'n': len(pair), 'a': mean_sd(a), 'b': mean_sd(b),
                         'difference': estimate, 't': outcome.statistic, 'df': df, 'p': outcome.pvalue,
                         'ci': mean_interval(estimate, se, df, alpha, alternative), 'effect': estimate/sd})
        effect_label = "Cohen's dz"
    headers += [Column('difference', _('均值差')), Column('t', 't'), Column('df', 'df'), Column('p', 'p', 'p'),
                Column('ci', _('%(level)s%%置信区间', level='%g' % (100*(1-alpha))), 'interval'), Column('effect', effect_label)]
    details.update(alternative=alternative, alpha=alpha, results=rows)
    return StatisticalResult([PaperTable(_('t检验结果'), headers, rows)], details)

查看完整模块 · 下载算法包 · 复现指南

复现本方法 ​

在解压目录安装 requirements.txt 后执行。样例为固定种子的模拟数据,仅供验证;输出不得冒充真实研究结果。

python
import examples._bootstrap
from examples.statistics_cases import build_data, method_cases
from core.statistical.runner import analyze

method = "stat_t_one_sample"
options = dict(method_cases())[method]
result = analyze(build_data(), method, options)
print(result.tables[0].html())

页面操作与解读教程

Released under the AGPL-3.0 License.