【科普】 Spearman 相关分析

最近在分析一波学习数据,有个很想确认的问题:答题次数更多的人,正确率是不是也更高?

这个问题看起来只要把两列数字放在一起就能回答。但有人答了几十次,有人答了几千次;有人本来基础就好,有人正在反复练习薄弱内容。直接看平均数,很容易把事情想简单。

此时就需要一个合适的工具:Spearman 相关分析(Spearman’s rank correlation analysis

,斯皮尔曼秩相关分析)

“秩”这个字有点唬人,把它理解成排名(英文原文就是rank,排名)就行。

举个例子

学员 答题次数 正确率
小王 20次 50%
小李 50次 60%
小张 100次 70%
小陈 300次 80%

按答题次数从少到多排:

小王 → 小李 → 小张 → 小陈。

按正确率从低到高排,还是

小王 → 小李 → 小张 → 小陈。

两份排名完全一致。这个例子的 Spearman 相关系数就是 +1。如果次序完全反过来,答题最多的人正确率最低,结果就是 −1。现实中多数情况没有这么整齐,算出来的数通常落在两者之间。

怎么用?

Spearman 相关系数(Spearman’s rank correlation coefficient)通常写作 ρ,也有人写 rₛ,范围是 −1 到 +1。

结果 可以怎样理解
接近 +1 两份排名通常同向:一个越高,另一个也倾向于越高
接近 0 看不出明显的同向或反向排名规律
接近 −1 两份排名通常反向:一个越高,另一个倾向于越低

为什么要这么做?

还是前面的例子。把小陈的答题次数从300次改为3,000次,只要其他数据不变,他仍然排在最后。两份排名都没变,Spearman 的结果也就不变。

所以,它更关注顺序是否一致,不会因为某一个人特别大的数值,就按数值大小给这个人特别大的影响。

与它经常一起出现的 Pearson 相关分析,更关注两列原始数值的线性关系,也就是它们是否大致沿一条直线变化。Spearman 则先看排名是否同向变化,不要求原始数值落在直线上。

不过,换成排名也意味着丢掉了一部分信息:20次和50次之间的差距,与100次和3,000次之间的差距,不能再直接体现在排名间隔里。

接近0,是不是说明“完全没关系”?

Spearman 擅长发现的是单调关系:一个变量增加时,另一个总体上越来越高,或者越来越低。

但有些关系不是单调关系,比如某个指标随着另一个指标增加,先上升又下降,形成倒U形。这样的关系很明显,Spearman 却可能接近0,因为前后两个方向互相抵消了。

最需要小心的是:相关不等于原因

假设真的发现,答题次数与正确率正相关。

我们只能说:在这批数据中,答题更多的人,正确率通常也更高。

还不能直接说:因为答题更多,所以正确率更高。

可能存在别的解释:基础好的学员更愿意多做题;不同学员做的题难度不同;反复做熟悉的题,也可能把累计正确率抬高。

反过来,如果相关系数很低,也不能说练习没有作用。有些人基础薄弱,练了很多后从20%提高到50%,但与原本就能答到80%的人相比,他的正确率仍然更低。把不同的人混在一起比较,可能看不见同一个人的进步。

因此,“多练的人是否通常答得更准”与“多练习能否让同一个人进步”,是两个不同的问题。后一个问题还需要前后对比,并尽量让题目难度、题源等条件可比。

扩展:这个系怎么算出来的?

先说计算链路:保留每个人的两列数据 → 分别换成排名 → 计算两列排名的相关系数。

注意,分别排名不等于把两列数据各自排序后重新拼在一起。小王的答题次数,必须始终对应小王的正确率。 如果打乱了人的对应关系,分析的就不是原来的问题了。

前面两份排名完全一致,所以结果是+1。现在只把小李和小张的正确率交换一下,看看怎么算出一个“不完全一致”的结果。

学员 答题次数 次数排名 R 正确率 正确率排名 S 排名差 d=R−S d²
小王 20次 1 50% 1 0 0
小李 50次 2 70% 3 −1 1
小张 100次 3 60% 2 1 1
小陈 300次 4 80% 4 0 0

把最后一列加起来:Σd²=0+1+1+0=2。当两列都没有并列排名时,可以用这个简化公式:

ρ = 1 − (6 × Σd²) / [n × (n² − 1)]

这里的n是人数,d是同一个人在两份排名中的差。代入这个例子:

n = 4
Σd² = 2

ρ = 1 − (6 × 2) / [4 × (4² − 1)]
  = 1 − 12 / 60
  = 0.8

所以结果是0.8。两份排名大体一致,但有两个人的位置交换了,没有达到完全一致的+1。

这个公式也能解释前面的两个极端情况:排名完全一致时,每个人的d都是0,结果为+1;在没有并列的情况下,次序完全相反时,结果为−1。

遇到并列数据的话,比如四个人的正确率是:

正确率:50%、60%、60%、80%
排名:  1、 2.5、2.5、 4

不能直接套上面的简化公式,这里就不展开说了,有兴趣的朋友可以自行检索学习

用 Python 验证一下

已经安装 SciPy 的话,可以这样计算刚才的例子:

from scipy.stats import spearmanr

attempts = [20, 50, 100, 300]
accuracy = [50, 70, 60, 80]

result = spearmanr(attempts, accuracy)
print(round(result.statistic, 3))  # 0.8

输入原始数值即可,函数会处理排名。这里读取的是系数statistic,不是pvalue。如果某一列所有人的数值完全相同,没有可比较的高低,系数无法定义,软件通常会返回nan并提示。SciPy 官方说明

同一批数据、同一套排名处理,得到的系数就是固定的。 后续添加的置信区间或p值,是在讨论估计的不确定性和统计证据,不会改变这个系数的计算结果。

最后总结一下

Spearman 帮我们看两份排名是否一起变化;它能发现关联,但不会自动告诉我们为什么。

参考:SciPy 官方文档:spearmanr