使用`loess.smooth`而不是`loess`或`lowess`时出错

时间:2011-01-10 10:20:02

标签: r smooth loess

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

> 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.smoothloess使用相同的估计函数,但前者是处理评估点的“辅助函数”。该错误似乎来自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 个答案:

答案 0 :(得分:8)

第1部分: 这需要一些追踪,但如果你这样做:

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

模型适合。这是由于loess.smoothloess的默认值不同而产生的;前者有family = c("symmetric", "gaussian")而前者有逆转。如果您浏览loessloess.smooth的代码,则会在family = "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

另请注意,loess.smooth的默认值与loess的默认值不同,例如适用于'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部分: 查看?try?tryCatch,您可以绕过黄土拟合函数(loess.smooth说),如果遇到loess.smooth中的错误,将允许计算继续。< / p>

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

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

我可能会将trytryCatchloess相匹配,并使用predict来解决此类问题。

答案 1 :(得分:0)

这是我第一次遇到这些功能,所以我无法帮助你,但这不能与y值的方差为0有关吗?现在,您尝试从已经尽可能平滑的数据中估计平滑线,这确实有效:

x <- 0:50
y <- c(rep(0,25),rep(1,26))
loess.smooth(x,y)