【Python・统计学】威尔科克森符号秩检验/Wilcoxon signed-rank test(原理及代码)

前言

自学笔记,分享给对统计学原理不太清楚但需要在论文中用到的小伙伴,欢迎大佬们补充或绕道。ps:本文不涉及公式讲解(文科生小白友好体质)~(部分定义等来源于知乎百度等)

本文重点:威尔科克森符号秩检验(英文名:Wilcoxon signed-rank test)

1.简单原理和步骤

2.应用条件

【3.数据实例以及Python代码

1.简单原理和步骤

  • 威尔科克森符号秩检验是一种非参数检验的方法,需要数据满足正态分布的假设,只要求数据分布大致对称。
  • 用于比较两组配对数据之间的差异。它的基本思路是,如果两组数据没有显著差异,那么它们之间的差值应该在正负两个方向上均匀分布。

具体来说,该检验方法按以下步骤进行:

  • 计算每对数据的差值。
  • 忽略差值为零的数据对。
  • 对剩下的差值取绝对值,并按从小到大的顺序排列,得到它们的排名(秩)。
  • 把差值为正的秩相加,得到正秩和;把差值为负的秩相加,得到负秩和。
  • 在原假设(两组数据无显著差异)为真的情况下,正秩和与负秩和应该相近。如果两者差异很大,则说明数据支持备择假设(两组数据存在显著差异)。
 补充1:关于参数检验非参数检验的使用条件想请参考以下两个说明:

【统计学】参数检验和非参数检验的使用条件(图表说明)icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/138028274

【统计学】参数检验和非参数检验的区别和基本统计学icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/137423304

补充2:本文适用于配对数据(例如:考试前成绩/考试后数据等来自同一试验者的两个数据)
独立样本检验请参照以下推文:

【Python・统计学】Mann-Whitney U检验/Wilcoxon秩和检验(原理及代码)icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/138028894

2.应用条件

  • 数据是成对的,即每个个体或对象都有两个相关的观测值。
  • 数据至少是顺序尺度的,即可以比较大小,但不要求数值之间的差异有意义。
  • 两组观测值的差值需要近似对称分布,但不必严格服从正态分布。
  • 样本量较小时(如n<30),该方法比t检验更为合适。
    但样本量太小时(如n<6),该方法的效能也会降低。
  • 当数据中存在大量(超过1/4)相同秩时,该方法的效能会受影响。

3.数据实例以及Python代码

(1)常用数据实例(病人服药前后的差异)

假设想知道一种新的减肥药是否有效,于是随机选择10个人,记录他们服用该药前后的体重,数据如下:

服药前: 80, 75, 90, 85, 70, 95, 100, 80, 85, 90

服药后: 75, 70, 85, 80, 65, 90, 95, 75, 80, 85

我们感兴趣的是每个人体重的变化量,即"服药前 - 服药后"。对这10个差值进行威尔科克森符号秩检验,如果结果显示正秩和与负秩和差异显著,就可以认为该减肥药有显著效果。

from scipy.stats import wilcoxon

# 服药前后的体重数据
before = [80, 75, 90, 85, 70, 95, 100, 80, 85, 90]
after = [75, 70, 85, 80, 65, 90, 95, 75, 80, 85]

# 进行配对威尔科克森符号秩检验
statistic, p_value = wilcoxon(before, after)

print(f'检验统计量为: {statistic}')
print(f'p值为: {p_value}')

if p_value < 0.05:
    print('在显著性水平0.05下,拒绝原假设,认为减肥药有显著效果')
else:
    print('在显著性水平0.05下,接受原假设,认为减肥药没有显著效果')
检验统计量为: 0.0
p值为: 0.001953125
在显著性水平0.05下,拒绝原假设,认为服药有显著效果

p值为0.001953125,表示在原假设(药物无效)为真的情况下,得到当前数据或更极端数据的概率。这里的p值远小于显著性水平0.05,因此我们拒绝原假设,认为药物有显著效果。

需要注意的是,这个例子中的数据比较理想,所有人服药后体重都有所下降。在实际应用中,数据可能没有这么"干净",因此p值和检验结论也可能不同。此外,显著性水平的选取(如0.05)取决于研究设计和领域惯例,并非绝对标准。

(2)进阶数据实例(教育学数据/需要数据清洗)

假设我们想研究一种新的教学方法是否能显著提高学生的数学成绩。我们随机选择了20名学生,记录了他们在使用新教学方法前后的数学测验成绩(满分100分)。但在数据录入过程中,有一些错误和遗漏的数据。原始数据如下:

before = [82, 75, 60, 'ab', 55, 74, 68, 90, 75, '', 85, 'x', 92, 85, 78, 80, 54, 67, 79, 200]
after = [85, 80, 62, 58, 'ba', 74, 70, '', 78, 92, '', 60, 88, 90, 82, 84, 65, 72, 80, -50]

可以看到,有些数据项是非数值的字符串,有些是空字符串以及输入错误的异常值(200和-50)

我们需要先清洗数据,再进行统计检验。 

(通过remove_outliers函数,去除了异常值(即z分数绝对值大于3的数据点),得到进一步清洗后的cleaned_beforecleaned_after。异常值200和-50被去除了)

import numpy as np
from scipy.stats import wilcoxon

# 数据清洗函数
def clean_data(data):
    cleaned_data = []
    for item in data:
        if isinstance(item, (int, float)):
            cleaned_data.append(item)
    return cleaned_data

# 去除异常值函数
def remove_outliers(data, threshold=3):
    z_scores = [(x - np.mean(data)) / np.std(data) for x in data]
    return [x for x, z in zip(data, z_scores) if abs(z) < threshold]

# 清洗数据
cleaned_before = clean_data(before)
cleaned_after = clean_data(after)

# 去除异常值
cleaned_before = remove_outliers(cleaned_before)
cleaned_after = remove_outliers(cleaned_after)

# 确保两组数据长度相等
min_len = min(len(cleaned_before), len(cleaned_after))
cleaned_before = cleaned_before[:min_len]
cleaned_after = cleaned_after[:min_len]

print(f'清洗和去除异常值后的数据对数: {min_len}')

再进行威尔科克森符号秩检验

# 进行配对威尔科克森符号秩检验
statistic, p_value = wilcoxon(cleaned_before, cleaned_after)

print(f'检验统计量为: {statistic}')
print(f'p值为: {p_value}')

if p_value < 0.05:
    print('在显著性水平0.05下,拒绝原假设,认为新教学方法可以显著提高数学成绩')
else:
    print('在显著性水平0.05下,接受原假设,认为新教学方法不能显著提高数学成绩')

 结果和说明

清洗和去除异常值后的数据对数: 15
检验统计量为: 12.5
p值为: 0.025802612304687467
在显著性水平0.05下,拒绝原假设,认为新教学方法可以显著提高数学成绩

从输出结果可以看到,清洗和去除异常值后的有效数据对数为15,比之前少了1对。这是因为我们在原始数据中添加了两个异常值,其中之一(200)在数据清洗后被过滤掉了。

尽管数据有所变化,但最终的检验结果仍然拒绝了原假设,支持新教学方法可以显著提高数学成绩的结论。

这个例子展示了在数据分析中,除了处理非数值类型的数据外,还需要注意识别和处理异常值。异常值可能来自数据录入错误、测量偏差或真实的极端情况,如果不加处理,可能会严重影响统计分析的结果。常用的异常值处理方法包括删除、替换、盖编码等,需要根据具体情况选择合适的方法。

你可能感兴趣的:(统计学,python,python,学习,笔记)