7

我需要平滑一些模拟数据,但是当要平滑的模拟坐标大多是相同的值时,偶尔会遇到问题。这是最简单情况的一个可重复的小示例。

> x <- 0:50
> y <- rep(0,51)
> loess.smooth(x,y)
Error in simpleLoess(y, x, w, span, degree, FALSE, FALSE, normalize = FALSE,  : 
   NA/NaN/Inf in foreign function call (arg 1)

loess(y~x), lowess(x,y), 和它们在 MATLAB 中的类似物在这个例子中产生了预期的结果而没有错误。我在loess.smooth这里使用是因为我需要在一定数量的点上评估估计值。根据文档,我相信loess.smooth并且loess正在使用相同的估计函数,但前者是处理评估点的“辅助函数”。错误似乎来自 C 函数:

> traceback()
3: .C(R_loess_raw, as.double(pseudovalues), as.double(x), as.double(weights), 
   as.double(weights), as.integer(D), as.integer(N), as.double(span), 
   as.integer(degree), as.integer(nonparametric), as.integer(order.drop.sqr), 
   as.integer(sum.drop.sqr), as.double(span * cell), as.character(surf.stat), 
   temp = double(N), parameter = integer(7), a = integer(max.kd), 
   xi = double(max.kd), vert = double(2 * D), vval = double((D + 
       1) * max.kd), diagonal = double(N), trL = double(1), 
   delta1 = double(1), delta2 = double(1), as.integer(0L))
2: simpleLoess(y, x, w, span, degree, FALSE, FALSE, normalize = FALSE, 
   "none", "interpolate", control$cell, iterations, control$trace.hat)
1: loess.smooth(x, y)

loess也调用simpleLoess,但似乎有不同的论点。当然,如果你改变足够多的 y 值使其不为零,loess.smooth则运行不会出错,但我需要程序在最极端的情况下运行。

希望有人可以帮助我完成以下一项和/或全部工作:

  1. 了解为什么只有loess.smooth而不是其他函数会产生此错误并找到解决此问题的方法。
  2. 找到一种解决方法,使用loess但仍评估与向量 x 不同的指定点数的估计值。例如,我可能只想x <- seq(0,50,10)在平滑中使用,但在 处评估估计x <- 0:50。据我所知,使用predict新的数据框无法正确处理这种情况,但如果我在那里遗漏了什么,请告诉我。
  3. 以不会阻止程序移动到下一个模拟数据集的方式处理错误。

在此先感谢您对此问题的任何帮助。

4

2 回答 2

8

对于第 1 部分: 这需要进行一些跟踪,但如果您这样做:

loess.smooth(x, y, family = "guassian")

该模型将适合。这是由于 和 的不同默认值引起loess.smoothloess;前者有family = c("symmetric", "gaussian"),后者则相反。如果您浏览 and 的代码loessloess.smooth您会看到 whenfamily = "gaussian" iterations设置为1。否则它取值loess.control()$iterations。如果在 中进行迭代simpleLoess,则以下函数调用将返回 的向量NaN

pseudovalues <- .Fortran(R_lowesp, as.integer(N), as.double(y), 
            as.double(z$fitted.values), as.double(weights), as.double(robust), 
            integer(N), pseudovalues = double(N))$pseudovalues

这会导致下一个函数调用抛出您看到的错误:

zz <- .C(R_loess_raw, as.double(pseudovalues), as.double(x), 
            as.double(weights), as.double(weights), as.integer(D), 
            as.integer(N), as.double(span), as.integer(degree), 
            as.integer(nonparametric), as.integer(order.drop.sqr), 
            as.integer(sum.drop.sqr), as.double(span * cell), 
            as.character(surf.stat), temp = double(N), parameter = integer(7), 
            a = integer(max.kd), xi = double(max.kd), vert = double(2 * 
                D), vval = double((D + 1) * max.kd), diagonal = double(N), 
            trL = double(1), delta1 = double(1), delta2 = double(1), 
            as.integer(0L))

这都与黄土中的稳健拟合(方法)有关。如果您不想要/不需要坚固的合身,请family = "gaussian"在您的loess.smooth通话中使用。

另外,请注意 for 的默认值与 的默认值loess.smooth不同loess,例如 for'span''degree'。因此,请仔细检查您要适合的模型并调整相关功能的默认值。

对于第 2 部分:

DF <- data.frame(x = 0:50, y = rep(0,51))
mod <- loess(y ~ x, data = DF)
pred <- predict(mod, newdata = data.frame(x = c(-1, 10, 15, 55)))
mod2 <- loess(y ~ x, data = DF, control = loess.control(surface = "direct"))
pred2 <- predict(mod2, newdata = data.frame(x = c(-1, 10, 15, 55)))

这使:

> pred
 1  2  3  4 
NA  0  0 NA 
> pred2
1 2 3 4 
0 0 0 0

如果那是您的意思,则默认值不会外推。predict事实上,我根本看不出使用这里有什么问题。

对于第 3 部分: 看看你可以围绕 loess 拟合函数(比如说),如果遇到错误?try,它将允许计算继续进行。?tryCatchloess.smoothloess.smooth

您将需要处理trytryCatch包含类似的输出(如果您在循环中执行此操作:

mod <- try(loess.smooth(x, y))
if(inherits(mod, "try-error"))
    next
## if here, model work, do something with `mod`

对于这样的问题,我可能会结合trytryCatch配合通过loess和使用。predict

于 2011-01-10T10:44:47.260 回答
0

这是我第一次遇到这些函数,所以我帮不了你太多,但这难道与 y 值的方差为 0 有关系吗?现在,您尝试从已经尽可能平滑的数据中估计出一条平滑线,这确实有效:

x <- 0:50
y <- c(rep(0,25),rep(1,26))
loess.smooth(x,y)
于 2011-01-10T10:36:32.803 回答