kstest给出奇怪的p值

时间:2019-06-19 12:53:10

标签: python scipy kolmogorov-smirnov

我想检查概率是否来自经验CDF指定的分布。 skill_id 12204给出了我认为是错误的p值;怎么了?

我编写了一个测试函数来验证p值。我正在比较来自两个相同分布的样本数组,并检查从#!/usr/bin/env perl use strict; use warnings; use Net::Works::Network (); use Try::Catch qw( catch try ); my $network; try { $network = Net::Works::Network->new_from_string( string => '148.64.0.0/224' ); } catch { print "Not a valid network: $_\n"; }; # ... maybe do something with $network here kstest函数获得的p值。由于原假设为真(分布相同),因此p值必须均匀地分布在[0,1]上,换句话说,我必须看到虚假发现率等于使用的p值阈值。 但是,只有kstest函数给出的p值才是这种情况。

ks_2samp

输出为

ks_2samp

我希望两个fdr值都接近0.05,但是from scipy import stats from statsmodels.distributions.empirical_distribution import ECDF def test(): num_runs = 1000 detected_kstest= 0 detected_ks_2samp = 0 for _ in range(num_runs): data1 = stats.norm.rvs(size=100, loc=1.0, scale=1.0) data2 = stats.norm.rvs(size=100, loc=1.0, scale=1.0) ecdf = ECDF(data1) p_threshold = 0.05 _, p_val = stats.kstest(data2, ecdf) if p_val < p_threshold: detected_kstest += 1 _, p_val = stats.ks_2samp(data1, data2) if p_val < p_threshold: detected_ks_2samp += 1 print(f'FDR for p-value threshold {p_threshold} : kstest: {detected_kstest / num_runs}, ks_2samp: {detected_ks_2samp / num_runs}') 给出的值很奇怪(太高了-换句话说,FDR for p-value threshold 0.05 : kstest: 0.287, ks_2samp: 0.051经常坚持认为数据来自不同的分布)。 / p>

我想念什么吗?

更新

如下所述,原因是kstest不能很好地处理小样本生成的ecdf ... las,我必须通过不是很大的样本来生成经验CDF。 现在,作为一种快速的解决方法,我使用一些“混合”方法:

kstest

因此可以将ECDF生成中使用的样本数量作为参数。也许这在数学上并不严格,到目前为止,这是我能想到的最好的方法。 在大小均为100的data1和data2上测试时,它给出了

kstest

2 个答案:

答案 0 :(得分:0)

您计算出的正态分布的ECDF近似,但是如果您使用该ECDF测试来自实际正态分布的足够大的样本,kstest将检测样品不是来自ECDF。毕竟,ECDF不是正态分布。

显然,样本大小为100(来自实际正态分布)足够大,以致kstest经常检测到这些样本不是来自与基于data1的ECDF相关联的分布。 / p>

如果在固定data1大小的同时增加data2的大小,最终将得到您期望的结果。通过增加data1的大小,可以提高ECDF逼近实际正态分布的程度。

当我将data1的创建更改为

        data1 = stats.norm.rvs(size=5000, loc=1.0, scale=1.0)

这就是我得到的:

In [121]: test()                                                                                     
FDR for p-value threshold 0.05 : kstest: 0.048, ks_2samp: 0.0465

In [122]: test()                                                                                     
FDR for p-value threshold 0.05 : kstest: 0.0515, ks_2samp: 0.0475

In [123]: test()                                                                                     
FDR for p-value threshold 0.05 : kstest: 0.0515, ks_2samp: 0.05

答案 1 :(得分:0)

所以我认为原因是ECDF函数产生阶跃函数并且不进行任何插值。 kstest如实地将分布与该“外观奇特”的阶跃函数进行比较,并且如果未进行校正以考虑到我们实际上是在处理阶跃函数(kstest的“ Smirnov”部分;这就是双面ks测试的作用。