
上个月接了个课程效果对比的数据需求某教育项目的两种授课方式线上视频课和线下小班课各随机抽出 6 名学生的单元测验成绩做比较。线下组是 76、78、79、80、82、85线上组是 87、88、90、91、93、95。需求一句话这两种方式到底有没有差别我拿到数据扫了一眼就决定不能直接上独立样本 t 检验——样本量这么小数据又明显不服从正态分布t 检验的假设撑不住。这种场景下真正顺手的是 Wilcoxon 秩和检验也叫 Mann-Whitney U 检验它不需要数据服从正态不关心总体分布长什么样只关心两组数据混在一起排完名次之后排名是不是一边倒偏向某一组。这篇文章我就从为什么非用不可讲起把秩rank的底层逻辑、完整手算过程、Python 和 R 的代码实现以及我自己实际踩过的坑一次性说透。适合正在学统计基础、或者被课程作业与真实业务数据逼着做两组比较的读者。1. t检验的软肋与秩和检验的出场前提1.1 正态性假设在真实数据里有多脆弱独立样本 t 检验的核心依赖是两个组的样本均值之差在零假设下近似服从 t 分布。这个近似能不能用取决于样本均值的抽样分布是否接近正态。大样本下中心极限定理能兜底但小样本只能依赖一条硬前提——数据本身来自正态总体。现实里这条前提经常破防。业务数据天生就是偏态的收入分布右拖尾用户评分 90% 的人打 5 星转化率一堆 0 和 1哪有什么正态。我这个项目的数据更典型线下组集中在 76-85 分线上组整体压到 87-95 分两堆数据别说正态连重叠都不多。真要硬跑 t 检验先不说检验功效被分布拖累光是被问你验证过正态性吗就得理亏三分。可能有人说先跑个 Shapiro-Wilk 检验p 大于 0.05 不就能用 t 检验了吗这里有个小样本特有的尴尬样本量一小平局的时候很少但其实正常分布的形状信息也少Shapiro-Wilk 对 6 个数据的偏态几乎没分辨力很容易给出不拒绝正态的结论然后把人带进沟里。检验的目的不是找到可以跑 t 检验的数据而是对数据做诚实的推断。1.2 两组有没有差别其实有两种问法很多人做两组比较时默认差别就等于均值有差别这个默认在不少场景下是错的。均值差只是位置参数的一种度量而且对离群值极其敏感一组数据里混进一个异常高值均值可能被拉出好几个标准差。更贴近业务直觉的问法是随机从两个组里各取一个样本A 组取值大于 B 组取值的概率是多少是不是显著偏离 50%这跟你关心两个班谁整体更强是同一个问题但不要求数据符合任何分布形状。Wilcoxon 秩和检验回答的正是这个问题它在零假设下要求两组分布相同备择假设是一组随机占优于另一组统计学上叫随机占优。这两种问法不冲突。数据接近正态时秩和检验和 t 检验通常给出相似结论数据偏离正态时秩和检验明显更稳。如果数据真的来自正态总体秩和检验的效率大约是 t 检验的 95%几乎打平可一旦分布偏一点、尾重一点秩和检验可以反超 t 检验。所以我的习惯是样本量不大、分布情况不明、又存在离群值嫌疑的两组比较直接默认秩和检验不纠结。2. 秩Rank把数值换成名次的底层逻辑2.1 排序编号就是最朴素的信息压缩秩这个概念一点也不神秘。把两组数据混在一起从小到大排队每个数据获得的名次就是它的秩。比如五个成绩 62、81、75、68、90从小到大排序后分别是 62第 1 名、68第 2 名、75第 3 名、81第 4 名、90第 5 名那它们的秩就是 1、2、3、4、5。如果两个同样大小的 82 分同时排在并列第 3 和第 4 名每个都取平均秩 3.5这叫做平均秩处理。考试出成绩的时候大家更关心排名而不是具体分数这个直觉放在统计里也一样当两个群体的数值分布形态完全不同时直接比分数没有意义比相对位置才有意义。秩就是把每个分数压缩成一个相对位置信息丢掉绝对数值只保留大小次序。2.2 丢掉数值反而更稳的原因有人会问明明分数是更精确的信息为什么丢掉它反而更可靠原因在于极端值对秩的影响被天然限制住了。一组数据里混入一个 10000 分它在排序里的秩最多是全体数据的最大值而均值会被它拉得一塌糊涂。秩只关心谁在前谁在后不关心前后差多少这让它对离群值的耐受力远强于基于均值的检验。更深一层秩带来了分布自由distribution-free的性质。秩的零分布只取决于样本量不取决于数据到底来自正态、均匀、指数还是什么奇怪的分布。因为从原始数据到秩相当于对任意连续分布做了一个固定的、单调的变换。这就是非参数检验的底气所在它不假设总体分布而假设的只是两组数据在排名上没有系统性差异。2.3 秩和检验的检验统计量到底在累加什么有了秩检验思路就变得很朴素如果两组没有差别混在一起排序后两组的秩应该均匀混合每组秩的总和秩和都应该接近理论期望值如果一组系统性偏大它的秩会普遍靠后秩和就会明显偏高另一组秩和明显偏低。回到我的例子线下组 6 个分数全部分布在整体排名的前 6 名线上组全占了后 6 名。如果两组真是来自同一分布这种完全分离出现的概率极小。秩和检验就是把这个直觉量化成 p 值。下一节我完整手算一遍大家就能看到整个机制的运转过程。3. 手把手算一遍从合并排序到p值3.1 示例数据与完整排序过程样本数据如下线上视频课组A 组87、88、90、91、93、95线下小班课组B 组76、78、79、80、82、85把 12 个数据混在一起从小到大排序给每个数据编上名次得分组别秩76线下178线下279线下380线下482线下585线下687线上788线上890线上991线上1093线上1195线上12没有并列分数所以不需要平均秩。3.2 秩和、U统计量与z值的换算先算两组的秩和。A 组的秩和 R_A 789101112 57B 组的秩和 R_B 123456 21两组秩和加起来等于 78恰好等于 1 到 12 的总和 12×13/2说明排队和编秩没有出错。在零假设两组分布相同下A 组理论期望秩和是 n₁(N1)/2 6×13/2 39。A 组实际秩和 57 比期望高了 18这个偏离有多大标准误为 sqrt(n₁n₂(N1)/12) sqrt(6×6×13/12) ≈ 6.245于是 z (57 - 39) / 6.245 ≈ 2.88。查标准正态分布表双尾 p 约为 0.004。统计软件里更常见的 U 统计量也顺手算一下U_A R_A - n₁(n₁1)/2 57 - 21 36 U_B R_B - n₂(n₂1)/2 21 - 21 0U_A U_B 36 n₁×n₂正好是全部两两配对的数量。这个 36 还有一个非常直观的解释A 组 6 个分数对 B 组 6 个分数一共形成 6×636 对比较A_B 各取其一在这 36 对里A 组分数全部大于 B 组分数所以 A 组赢了36 次一次都没输。完全分离的结构让这个检验的结论异常清晰。3.3 显著性怎么理解把检验结果翻译成人话p 值 0.004 意味着什么它说的是如果两组本质上没有差别仅靠随机抽样就得到A 组秩和比期望高 18 分甚至更极端这样的结果概率只有约 0.004正态近似下。换句话说A 组集体碾压 B 组这个现象很难用运气来解释更合理的结论是两组确实存在系统差异。顺便提一个精确检验的说法两组各 6 个、无平局时所有可能排序共有 C(12,6)924 种。像这样完全分离的极端情况只有 2 种A 全大或 B 全大所以精确双尾 p 值 2/924 ≈ 0.0022。数值和正态近似的 0.004 略有差异但结论不变。小样本且无平局时统计软件会倾向使用精确置换 p 值。这里我要特别强调一个理解上的关键秩和检验的结论不是A 组平均分显著高于 B 组而是随机抽取时A 组分数高于 B 组分数的概率显著大于 50%。这个措辞差别在下文坑与经验里还要细讲。4. 它和Mann-Whitney U检验到底是什么关系4.1 两个名字一套算法Wilcoxon 秩和检验由 Wilcoxon 在 1945 年提出第二年 Mann 和 Whitney 独立提出了一个数学上完全等价的方法。前者直接讨论秩和后者从两两比较谁更胜一筹的胜率角度切入最后两人发现殊途同归。所以教材和软件里两个名字混着用本质是同一套算法只是统计量的表达形式不同。两种形式可以互相转换。先算出第一组的秩和 R₁曼-惠特尼 U 值定义为 U₁ R₁ - n₁(n₁1)/2这可以理解为第一组在每个两两比较中胜出的次数U₂ n₁n₂ - U₁ 则是第二组胜出的次数。检验假设只跟 U₁ 的大小有关。所以看到软件输出 U 或者 W 都不要慌看明白它定义的是哪个量就行。4.2 不同软件输出对照与符号陷阱不同软件输出同一个检验时报告的统计量命名相当混乱这是我见过初学者栽跟头最多的地方。软件/工具输出统计量本例数值说明R 的 wilcox.testW36默认报告第一组对应的 U 值Python 的 scipy.stats.ranksumsz约 2.88基于第一组秩和的正态近似 z 值Python 的 scipy.stats.mannwhitneyuU36报告第一组的 U 值SPSS 的 Mann-Whitney 检验U 和 Wilcoxon WU36W21这里的 W 是两组秩和中较小的那个即 21SAS 的 NPAR1WAYWilcoxon S21S 通常取较小的秩和同样的分析R 给你 W36SPSS 给你 Wilcoxon W21你要是只记W21拿去写报告换个软件就接不上。正确做法是写报告时明确写出是第一组的秩和还是曼-惠特尼 U或者干脆把 z 值和 p 值作为主要汇报内容绕开这些命名差异。4.3 别跟配对的Wilcoxon符号秩检验搞混名字只差两个字用途完全不同。本文说的秩和检验适用于两个独立样本比如两组不同学生Wilcoxon 符号秩检验适用于配对样本比如同一组学生培训前和培训后的成绩。后者对每对数据的差值做排序统计的是正差值的秩和逻辑上跟单样本中位数检验更亲近。论文里如果把独立样本当配对样本处理等于凭空把样本量翻倍会夸大检验功效、制造虚假的显著性这是严重的统计错误。判断标准就一条两组数据能否天然一一对应。能用同一批对象的两个时间点或者操作配对说清楚的才是配对。5. Python和R实操直接能抄的代码5.1 Pythonscipy一行搞定与U值输出Python 里最常用的是 scipy.stats 的 ranksums 和 mannwhitneyu前者直接给正态近似的 z 和 p后者给 U 值二者计算的检验完全等价。import numpy as np from scipy.stats import ranksums, mannwhitneyu online np.array([87, 88, 90, 91, 93, 95]) offline np.array([76, 78, 79, 80, 82, 85]) # Wilcoxon 秩和检验正态近似 z, p ranksums(online, offline) print(fz {z:.3f}, p {p:.4f}) # 输出约为z 2.882, p 0.0039 # Mann-Whitney U 版本无平局、小样本时自动用精确置换 U, p_u mannwhitneyu(online, offline, alternativetwo-sided) print(fU {U:.1f}, p {p_u:.4f}) # 输出约为U 36.0, p 0.0022注意两种函数给出的 p 值有细微差别ranksums 用正态近似mannwhitneyu 在无平局、单组样本量不超过 8 时会自动换成精确置换检验所以 p 更小一点。两者结论一致。如果在 mannwhitneyu 里加参数 methodasymptoticp 也会变成和 ranksums 相近的 0.0039。5.2 Rwilcox.test的默认输出解读R 的做法更简洁一行函数自带精确检验online - c(87, 88, 90, 91, 93, 95) offline - c(76, 78, 79, 80, 82, 85) wilcox.test(online, offline)输出如下Wilcoxon rank sum test with continuity correction data: online and offline W 36, p-value 0.002165 alternative hypothesis: true location shift is not equal to 0这里 W36 就是第一组online对应的 U 值R 对无平局、样本量小于 50 的情况默认做精确置换检验所以 p 是 0.002165。想跑单侧检验加 alternativegreater 或 less想顺便估计组间中位数差加 conf.intTRUER 会给出 Hodges-Lehmann 中位数差估计和置信区间这是秩和检验自带的一种稳健效应量。5.3 报告规范p值之外还要写什么统计报告最忌讳只丢一个 p 值。我的例行做法是描述统计中位数和四分位距 检验统计量与 p 值 效应量三件套一起给。对上面这个例子可以写线上组成绩中位数 90.5 分Q1-Q3: 88-93线下组 79.5 分78-82。Mann-Whitney U 36z 2.88p 0.002精确置换。秩二列相关 r 1.0表明 100% 的两两比较中线上组得分高于线下组。秩二列相关rank-biserial correlation是秩和检验最常用的效应量算法就是 r (U_A - U_B) / (n₁n₂)我的例子中等于 (36-0)/36 1.0代表完全分离的强效应。它回答的是差异有多大p 值只回答差异是否显著业务复盘的时候前者往往更有决策价值。6. 踩过的坑与几条实用经验6.1 平局并列数据怎么处理实际数据没有教材里那么干净经常出现得分并列。处理方法就是前面说过的平均秩。举个简单的三对三例子A 组 85、91、92B 组 80、80、88。排序后第 1、2 名都是 80各自取平均秩 1.5后面 85 是第 3 名88 是第 4 名91 是第 5 名92 是第 6 名。A 组秩和 356 14B 组秩和 1.51.54 7检验按这个修正后的秩进行。平局多了会压缩秩的变异让正态近似的方差偏小、p 偏乐观。R 里有连续性校正Python 的 ranksums 也会自动做并列修正。平局比例很高时比如有序评分数据 1-5 分这种建议直接上精确置换检验R 里 wilcox.test 遇到平局会自动回退到正态近似我这时会用第三方包做更稳妥的精确检验。6.2 样本量小到什么程度检验会没力气秩和检验再稳健也扛不住样本量过小。一个常被忽略的事实是每组 3 个样本时就算两组数据完全分离精确双尾 p 值也只有 2/C(6,3) 0.1永远达不到 0.05。换句话说三对三的设计从数学上就注定了你不可能检验出显著差异。每组 4 个样本时完全分离的极端情况也只能给出双尾 p 2/C(8,4) ≈ 0.029勉强跨进显著门槛。所以项目设计阶段就要想清楚样本量。先用功效分析估算或者干脆做个简单模拟给两组设定一个预期差值模拟抽样跑几百次秩和检验看看检验功效能不能达到 80%。这两种方式都比事后补救强得多。6.3 显著结果不等于中位数显著不同这是我最想提醒的一个概念陷阱。很多资料为了好理解把秩和检验解释成比较两组中位数这个说法只在两组分布形状相同专业叫位置偏移假设时成立。一旦两组分布形状不同比如一组对称、一组偏态秩和检验显著不代表中位数有差异它只能说明随机从两组取一个值比较时一方有系统优势。所以汇报结果时我通常不写中位数显著不同而是写随机配对比较中A 组取值高于 B 组的比例显著大于 50%并且配上盒须图或密度图展示两组分布形状。如果双方分布的偏移近似平移这时再谈中位数差异才有统计学依据。6.4 要不要先跑正态性检验再决定用哪个检验有人习惯先跑 Shapiro-Wilk显著就用秩和不显著就用 t 检验。我不推荐这个流程原因有两个。第一小样本下正态性检验功效很低明明数据明显偏态也可能给出不显著然后你用了一个前提不成立的检验第二这种先做假设检验、再根据结果选检验的两步流程会扭曲最终检验的第一类错误率——你以为显著性水平是 0.05实际上可能远不是。更稳的做法在设计方案阶段就定好主检验不事后看 p 值挑方法。对两组独立样本如果样本量不大比如每组 30 以下、分布形态不清、数据可能偏态直接把秩和检验作为主检验如果行业惯例必须报 t 检验那就两个都跑作为敏感性分析互相印证。这样做出的结论比任何事后挑检验都更经得起推敲。实际给那个课程项目出报告时我用的就是线上组中位数 90.5 对线下组 79.5、U36、精确 p0.002、秩二列相关 r1.0 这组数据配上盒须图管理层一眼就明白线上教学在本次小样本测验中表现更优。后来项目扩到每班五十人重跑一遍结论依然稳定——这恰好说明当初选秩和检验这个决定是站得住的。两组比较这件事先想清楚要回答什么问题再选检验工具别一上来就 t 检验也别小看排队编号这种看起来简单的办法很多实际问题它都扛得住。