Python Scipy中的双样本Kolmogorov-Smirnov测试

chhqkbe1  于 2023-05-07  发布在  Python
关注(0)|答案(3)|浏览(156)

我不知道如何在Scipy中进行双样本KS测试。
在阅读了scipy kstest的文档之后,我可以看到如何测试分布是否与标准正态分布相同

from scipy.stats import kstest
import numpy as np

x = np.random.normal(0,1,1000)
test_stat = kstest(x, 'norm')
#>>> test_stat
#(0.021080234718821145, 0.76584491300591395)

这意味着在p值为0.76时,我们不能拒绝两个分布相同的零假设。
然而,我想比较两个分布,看看我是否可以拒绝零假设,即它们是相同的,比如:

from scipy.stats import kstest
import numpy as np

x = np.random.normal(0,1,1000)
z = np.random.normal(1.1,0.9, 1000)

并测试xz是否相同。
我试着天真的:

test_stat = kstest(x, z)

并得到以下错误:

TypeError: 'numpy.ndarray' object is not callable

有没有一种方法可以在Python中进行双样本KS测试?如果是的话,我应该怎么做?

8tntrjer

8tntrjer1#

您正在使用单样本KS检验。您可能需要双样本测试ks_2samp

>>> from scipy.stats import ks_2samp
>>> import numpy as np
>>> 
>>> np.random.seed(12345678)
>>> x = np.random.normal(0, 1, 1000)
>>> y = np.random.normal(0, 1, 1000)
>>> z = np.random.normal(1.1, 0.9, 1000)
>>> 
>>> ks_2samp(x, y)
Ks_2sampResult(statistic=0.022999999999999909, pvalue=0.95189016804849647)
>>> ks_2samp(x, z)
Ks_2sampResult(statistic=0.41800000000000004, pvalue=3.7081494119242173e-77)

结果可解释如下:
1.您可以根据样本大小将python给出的statistic值与KS-test critical value table值进行比较。当statistic值大于临界值时,两种分布不同。
1.或者,您可以将p-value与显著性水平 a 进行比较,通常a=0.05或0.01(您可以决定,a越低,越显著)。如果p值小于 a,则很可能两个分布不同。

jobtbby3

jobtbby32#

这就是scipy docs所说的:
如果K-S统计量很小或p值很高,则我们不能拒绝两个样本的分布相同的假设。
不能拒绝并不意味着我们确认。

jhdbpxl9

jhdbpxl93#

由于scipy 1.5.0scipy.stats.kstest执行双样本Kolmogorov-Smirnov测试,如果传递给它的第二个参数是一个类似数组的参数(numpy数组,Python列表,pandas Series等);换句话说,OP的代码产生了预期的结果。这是因为在内部,如果可以从输入解析scipy.stats中的分布,则调用ks_1samp,否则调用ks_2samp。所以kstest包含了两者。

import numpy as np
from scipy import stats

x = np.random.normal(0, 1, 1000)
z = np.random.normal(1.1, 0.9, 1000)

stats.kstest(x, stats.norm.cdf) == stats.ks_1samp(x, stats.norm.cdf)  # True
stats.kstest(x, z) == stats.ks_2samp(x, z)                            # True
如何解读结果?

双样本K-S检验提出的问题是,* 如果两个样本来自相同的分布 *,那么看到所提供的两个样本的可能性有多大。因此,零假设是样本来自相同的分布。
小的p值意味着我们不拒绝零假设。因此,在下面的例子中,p值非常小,这意味着我们拒绝零假设,并得出结论,两个样本xz不是来自相同的分布。

stats.kstest(x, z)
# KstestResult(statistic=0.445, pvalue=1.8083688851037378e-89, statistic_location=0.6493521689945357, statistic_sign=1)

事实上,如果我们绘制xz的经验累积分布,它们非常清楚地不重叠,这支持了上面执行的K-S检验的结果。

另一方面,如果两个样本如下所示(均来自具有相同平均值和非常接近的标准差的正态分布),则K-S检验的p值非常大,因此我们不能拒绝零假设,即它们来自相同的分布。

x = np.random.normal(0, 1, 1000)
z = np.random.normal(0, 0.9, 1000)

stats.kstest(x, z)
# KstestResult(statistic=0.04, pvalue=0.4006338815832625, statistic_location=0.07673397024028321, statistic_sign=1)

事实上,如果我们绘制这两个样本的经验累积函数,会有大量的重叠,这支持了K-S检验的结论。

请注意,不拒绝null并不意味着我们得出结论,这两个样本来自相同的分布,它只是意味着我们不能拒绝给定两个样本的null。
生成累积分布图的代码:

import seaborn as sns
import pandas as pd
sns.ecdfplot(pd.DataFrame({'x': x, 'z': z}))

相关问题