Kolomogorov-Smirnov测试:C到R的翻译问题

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翻译成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.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))