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

San*_*ndy 7 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)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

loess也呼吁simpleLoess,但似乎是不同的论点.当然,如果你将y值变化为非零,loess.smooth运行没有错误,但我需要程序在最极端的情况下运行.

希望有人可以帮助我解决以下一个和/或全部问题:

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

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

Rei*_*son 8

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

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

该模型适合.这是由于和的默认值不同loess.smooth而产生的loess; 前者有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
Run Code Online (Sandbox Code Playgroud)

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

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))
Run Code Online (Sandbox Code Playgroud)

这一切都与黄土中的鲁棒拟合(方法)有关.如果您不想/需要健壮,请family = "gaussian"loess.smooth通话中使用.

另请注意,默认值loess.smoothloess(例如)'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)))
Run Code Online (Sandbox Code Playgroud)

这使:

> pred
 1  2  3  4 
NA  0  0 NA 
> pred2
1 2 3 4 
0 0 0 0
Run Code Online (Sandbox Code Playgroud)

如果这是你的意思,默认不会推断.predict事实上,我看不出在这里使用的问题是什么.

对于第3部分: 查看?try以及?tryCatch哪些可以包围黄土拟合函数(loess.smooth例如),这将允许在loess.smooth遇到错误时计算继续.

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

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

我可能会结合trytryCatch通过适合通过loess和使用predict这样的问题.