【问题标题】:Error using `loess.smooth` but not `loess` or `lowess`使用 `loess.smooth` 但不是 `loess` 或 `lowess` 时出错
【发布时间】:2011-01-10 10:20:02
【问题描述】:

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

> 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 &lt;- seq(0,50,10),但在x &lt;- 0:50 处评估估计值。据我所知,将predict 与新数据框一起使用将无法正确处理这种情况,但如果我在那里遗漏了什么,请告诉我。
  3. 以不阻止程序移动到下一个模拟数据集的方式处理错误。

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

【问题讨论】:

    标签: r smooth loess


    【解决方案1】:

    第 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))
    

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

    另外,请注意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 中的错误,则可以继续计算。

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

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

    我可能会将trytryCatch 与通过loess 拟合并使用predict 来解决此类问题。

    【讨论】:

    • 删除了我的答案,因为这和你现在发布的一样。
    • @Joris - 无需删除它。我正要为你的答案投票!
    • 我在 OP 问题的第 1 部分中添加了一些内容,说明为什么 loess.smooth 会因显示的问题而失败。
    • @Gavin :没问题,你的要完整得多。我正在尝试在 SO 站点上节省一些服务器空间;-)。
    • 非常感谢您提供的非常有帮助和彻底的回答!
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-15
      • 2011-11-24
      • 2020-06-30
      • 2019-05-19
      • 2013-01-03
      • 2014-03-08
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多