我想检查概率是否来自经验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
答案 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测试的作用。