spearmanr#
- scipy.stats.spearmanr(a, b=None, axis=0, nan_policy='propagate', alternative='two-sided')[源代码][源代码]#
计算斯皮尔曼相关系数及其对应的p值。
斯皮尔曼等级相关系数是一种非参数的单调性关系度量方法,用于衡量两个数据集之间的关系。与其他相关系数一样,该系数的取值范围在 -1 到 +1 之间,0 表示没有相关性。相关系数为 -1 或 +1 表示存在完全单调的关系。正相关表示随着 x 的增加,y 也增加。负相关表示随着 x 的增加,y 减少。
p 值大致表示一个不相关的系统产生数据集的概率,这些数据集的 Spearman 相关性至少与从这些数据集中计算出的相关性一样极端。尽管 p 值的计算并不对样本下的分布做出强假设,但它仅对非常大的样本(>500 个观测值)准确。对于较小的样本量,请考虑使用排列检验(参见下面的示例部分)。
- 参数:
- a, b1D 或 2D 数组类对象,b 是可选的
一个或两个包含多个变量和观测值的1-D或2-D数组。当这些数组是1-D时,每个数组代表一个单一变量的观测向量。对于2-D情况下的行为,请参见下面的``axis``。两个数组在``axis``维度上需要具有相同的长度。
- 轴int 或 None, 可选
如果 axis=0(默认),则每一列代表一个变量,行中包含观测值。如果 axis=1,关系将被转置:每一行代表一个变量,而列中包含观测值。如果 axis=None,则两个数组都将被展平。
- nan_policy{‘propagate’, ‘raise’, ‘omit’}, 可选
定义当输入包含 nan 时的处理方式。以下选项可用(默认是 ‘propagate’):
‘propagate’: 返回 nan
‘raise’: 抛出一个错误
‘omit’: 执行计算时忽略 nan 值
- 替代方案{‘双侧’, ‘小于’, ‘大于’}, 可选
定义备择假设。默认是’双侧’。以下选项可用:
‘双边’: 相关性非零
‘less’: 相关性为负(小于零)
‘greater’: 相关性为正(大于零)
Added in version 1.7.0.
- 返回:
- res重要性结果
一个包含属性的对象:
- 统计浮点数或ndarray(2维方阵)
Spearman 相关矩阵或相关系数(如果仅给出两个变量作为参数)。相关矩阵是方形的,其长度等于
a
和b
中变量总数(列或行)。- p值浮动
对于一个假设检验的p值,其零假设是两个样本没有序数相关性。关于备择假设,请参见上面的 alternative。pvalue 与 statistic 具有相同的形状。
- 警告:
ConstantInputWarning
如果输入是一个常数数组,则会引发此错误。在这种情况下,相关系数未定义,因此返回
np.nan
。
参考文献
[1]Zwillinger, D. 和 Kokoska, S. (2000). CRC 标准概率与统计表及公式. Chapman & Hall: 纽约. 2000. 第14.7节
[2]Kendall, M. G. 和 Stuart, A. (1973). 《高级统计理论,第二卷:推理与关系》. Griffin. 1973. 第31.18节
[3]Kershenobich, D., Fierro, F. J., & Rojkind, M. (1970). 游离脯氨酸池与人类肝硬化中胶原含量的关系。临床研究杂志, 49(12), 2246-2249.
[4]Hollander, M., Wolfe, D. A., & Chicken, E. (2013). 非参数统计方法. John Wiley & Sons.
[5]B. Phipson and G. K. Smyth. “Permutation P-values Should Never Be Zero: Calculating Exact P-values When Permutations Are Randomly Drawn.” Statistical Applications in Genetics and Molecular Biology 9.1 (2010).
[6]Ludbrook, J., & Dudley, H. (1998). 为什么置换检验在生物医学研究中优于t检验和F检验。美国统计学家, 52(2), 127-132.
示例
考虑来自 [3] 的数据,该研究探讨了游离脯氨酸(一种氨基酸)与总胶原蛋白(一种常在结缔组织中发现的蛋白质)在不健康人肝脏中的关系。
下面的
x
和y
数组记录了两种化合物的测量值。观察值是成对的:每次游离脯氨酸测量都取自与相同索引处的总胶原蛋白测量相同的肝脏。>>> import numpy as np >>> # total collagen (mg/g dry weight of liver) >>> x = np.array([7.1, 7.1, 7.2, 8.3, 9.4, 10.5, 11.4]) >>> # free proline (μ mole/g dry weight of liver) >>> y = np.array([2.8, 2.9, 2.8, 2.6, 3.5, 4.6, 5.0])
这些数据在 [4] 中使用斯皮尔曼相关系数进行了分析,这是一种对样本间单调相关性敏感的统计量。
>>> from scipy import stats >>> res = stats.spearmanr(x, y) >>> res.statistic 0.7000000000000001
这个统计量的值对于具有强正序相关的样本往往会很高(接近1),对于具有强负序相关的样本会很低(接近-1),而对于具有弱序相关的样本,其值的大小会很小(接近零)。
测试是通过将统计量的观测值与零分布进行比较来进行的:零分布是在总胶原蛋白和游离脯氨酸测量相互独立的零假设下得出的统计量值的分布。
在这个测试中,统计量可以被转换,使得对于大样本的零分布是具有
len(x) - 2
自由度的学生 t 分布。>>> import matplotlib.pyplot as plt >>> dof = len(x)-2 # len(x) == len(y) >>> dist = stats.t(df=dof) >>> t_vals = np.linspace(-5, 5, 100) >>> pdf = dist.pdf(t_vals) >>> fig, ax = plt.subplots(figsize=(8, 5)) >>> def plot(ax): # we'll reuse this ... ax.plot(t_vals, pdf) ... ax.set_title("Spearman's Rho Test Null Distribution") ... ax.set_xlabel("statistic") ... ax.set_ylabel("probability density") >>> plot(ax) >>> plt.show()
比较通过p值量化:零分布中与统计量的观测值同样极端或更极端的值的比例。在统计量为正的双侧检验中,零分布中大于转换后统计量的元素和零分布中小于观测统计量负值的元素都被视为“更极端”。
>>> fig, ax = plt.subplots(figsize=(8, 5)) >>> plot(ax) >>> rs = res.statistic # original statistic >>> transformed = rs * np.sqrt(dof / ((rs+1.0)*(1.0-rs))) >>> pvalue = dist.cdf(-transformed) + dist.sf(transformed) >>> annotation = (f'p-value={pvalue:.4f}\n(shaded area)') >>> props = dict(facecolor='black', width=1, headwidth=5, headlength=8) >>> _ = ax.annotate(annotation, (2.7, 0.025), (3, 0.03), arrowprops=props) >>> i = t_vals >= transformed >>> ax.fill_between(t_vals[i], y1=0, y2=pdf[i], color='C0') >>> i = t_vals <= -transformed >>> ax.fill_between(t_vals[i], y1=0, y2=pdf[i], color='C0') >>> ax.set_xlim(-5, 5) >>> ax.set_ylim(0, 0.1) >>> plt.show()
>>> res.pvalue 0.07991669030889909 # two-sided p-value
如果 p 值是“小”的——也就是说,如果从独立分布中抽取数据产生如此极端的统计值的概率很低——这可能被视为反对零假设而支持备择假设的证据:总胶原蛋白和游离脯氨酸的分布 不 是独立的。请注意:
反之则不然;也就是说,测试并不用于为零假设提供证据。
被认为是“小”的值的阈值是一个选择,应在分析数据之前做出 [5] ,同时考虑到假阳性(错误地拒绝零假设)和假阴性(未能拒绝错误的零假设)的风险。
小的p值并不是*大*效应的证据;相反,它们只能提供“显著”效应的证据,这意味着它们在零假设下不太可能发生。
假设在进行实验之前,作者有理由预测总胶原蛋白和游离脯氨酸测量值之间存在正相关,并且他们选择评估零假设相对于单侧备择假设的合理性:游离脯氨酸与总胶原蛋白具有正序相关性。在这种情况下,只有那些在零分布中等于或大于观察到的统计量的值被认为是更极端的。
>>> res = stats.spearmanr(x, y, alternative='greater') >>> res.statistic 0.7000000000000001 # same statistic >>> fig, ax = plt.subplots(figsize=(8, 5)) >>> plot(ax) >>> pvalue = dist.sf(transformed) >>> annotation = (f'p-value={pvalue:.6f}\n(shaded area)') >>> props = dict(facecolor='black', width=1, headwidth=5, headlength=8) >>> _ = ax.annotate(annotation, (3, 0.018), (3.5, 0.03), arrowprops=props) >>> i = t_vals >= transformed >>> ax.fill_between(t_vals[i], y1=0, y2=pdf[i], color='C0') >>> ax.set_xlim(1, 5) >>> ax.set_ylim(0, 0.1) >>> plt.show()
>>> res.pvalue 0.03995834515444954 # one-sided p-value; half of the two-sided p-value
需要注意的是,t分布提供了零分布的渐近近似;它仅对具有大量观测值的样本准确。对于小样本,进行置换检验可能更为合适:在总胶原蛋白和游离脯氨酸相互独立的零假设下,每个游离脯氨酸测量值与任何总胶原蛋白测量值配对的可能性是均等的。因此,我们可以通过计算``x``和``y``之间每个可能元素配对下的统计量来形成一个*精确*的零分布。
>>> def statistic(x): # explore all possible pairings by permuting `x` ... rs = stats.spearmanr(x, y).statistic # ignore pvalue ... transformed = rs * np.sqrt(dof / ((rs+1.0)*(1.0-rs))) ... return transformed >>> ref = stats.permutation_test((x,), statistic, alternative='greater', ... permutation_type='pairings') >>> fig, ax = plt.subplots(figsize=(8, 5)) >>> plot(ax) >>> ax.hist(ref.null_distribution, np.linspace(-5, 5, 26), ... density=True) >>> ax.legend(['aymptotic approximation\n(many observations)', ... f'exact \n({len(ref.null_distribution)} permutations)']) >>> plt.show()
>>> ref.pvalue 0.04563492063492063 # exact one-sided p-value