Kolomogorov-Smirnov测试:C到R的翻译问题
我很难将一个算法从C翻译成R。这是关于Kolmogorov-Smirnov测试,更具体地说是KS概率函数Kolomogorov-Smirnov测试:C到R的翻译问题,c,r,kolmogorov-smirnov,C,R,Kolmogorov Smirnov,我很难将一个算法从C翻译成R。这是关于Kolmogorov-Smirnov测试,更具体地说是KS概率函数 在“C中的数字配方”中,“probks”的代码为 #include <math.h> #define EPS1 0.001 #define EPS2 1.0e-8 float probks(float alam) /*Kolmogorov-Smirnov probability function.*/ { int j; float a2,fac=2.0,sum=0.
在“C中的数字配方”中,“probks”的代码为
#include <math.h>
#define EPS1 0.001
#define EPS2 1.0e-8
float probks(float alam)
/*Kolmogorov-Smirnov probability function.*/
{
int j;
float a2,fac=2.0,sum=0.0,term,termbf=0.0;
a2 = -2.0*alam*alam;
for (j=1;j<=100;j++) {
term=fac*exp(a2*j*j);
sum += term;
if (fabs(term) <= EPS1*termbf || fabs(term) <= EPS2*sum) return sum;
fac = -fac; /*Alternating signs in sum.*/
termbf=fabs(term);
}
return 1.0; /* Get here only by failing to converge. */
}
编辑2
使用Konrad函数ks_cdf和
x = seq(0, 1, by = 0.01)
plot(x, ks_cdf(x))
仍然在0时给出0
编辑3
升级到3.6.1后
> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
...
我仍然得到与上面相同的图,即ks_cdf(0)=0,而它应该是ks_sdf(0)=1代码几乎可以从字面上翻译成R-不清楚为什么您无缘无故地偏离C代码。这里有一个字面的,稍微整理过的翻译:
ks_cdf = function (lambda) {
EPS1 = 0.001
EPS2 = 1.0e-8
sum = 0
fac = 2
termbf = 0
a2 = -2 * lambda ^ 2
for (j in 1 : 100) {
term = fac * exp(a2 * j ^ 2)
sum = sum + term
if ((abs(term) <= EPS1 * termbf) || (abs(term) <= EPS2 * sum)) {
return(sum)
} else {
fac = -fac
termbf = abs(term)
}
}
1 # Failed to converge.
}
只是为了澄清-(为什么)您不能使用内置函数
ks.test
?除此之外,这个错误是一个简单的输入错误:termfb
update需要在循环内部,而不是外部(在那里它是无用的),并且您更改了返回值,并且在这样做的过程中,没有考虑到收敛性的不足。顺便说一句,我知道内置函数。对于KS测试的2D版本,我需要它,虽然它由一个R包支持,但它没有显著性计算。谢谢,我不知道我可以在循环中执行“返回(求和)”!是的,矢量化是以这种方式进行的,但除了不能以简单的方式绘制cdf之外,这不是一个问题。顺便说一句,KS公式描述的是累积分布函数(CDF)而不是概率分布函数(PDF)。@mjs关于矢量化,我不同意,在R中,你应该将其视为一个问题。有关矢量化函数,请参见我的更新答案。理想情况下,我们可以去掉apply
语句,但我现在想不出一个好方法。它可以被一个colSums
代替,但我拒绝编写将逻辑值视为数字的代码,也不会使代码更短。哇!这样的代码让我抓狂,因为我永远都无法理解它,但它真的很酷。显然,我不是一个“母语人士”:(矢量化版本中似乎有一个错误,ks_cdf(0)=0,而它应该是ks_cdf(0)=1!@mjs我想这段代码不适用。但总的来说,这是一个完全不同的蠕虫。我相信这是由于我在这里尝试使用的滞后
函数。除了这是错误的事实(我们需要完全相反的,领先
,它在base R中不存在,但在dplyr中确实存在),它通常用于时间序列,可能会对矩阵做一些奇怪的事情。
> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
...
ks_cdf = function (lambda) {
EPS1 = 0.001
EPS2 = 1.0e-8
sum = 0
fac = 2
termbf = 0
a2 = -2 * lambda ^ 2
for (j in 1 : 100) {
term = fac * exp(a2 * j ^ 2)
sum = sum + term
if ((abs(term) <= EPS1 * termbf) || (abs(term) <= EPS2 * sum)) {
return(sum)
} else {
fac = -fac
termbf = abs(term)
}
}
1 # Failed to converge.
}
ks_cdf = function (λ) {
eps1 = 0.001
eps2 = 1E-8
range = seq(1, 100)
terms = (-1) ^ (range - 1) * exp(-2 * range ^ 2 %*% t(λ ^ 2))
sums = 2 * colSums(terms)
pterms = abs(terms)
prev_pterms = rbind(0, pterms[-nrow(pterms), , drop = FALSE])
converged = apply(pterms <= eps1 * prev_pterms | pterms <= eps2 * sums, 2L, any)
sums[! converged] = 1
sums
}
x = seq(0, 1, by = 0.01)
plot(x, ks_cdf(x))