在交叉验证中使用sapply

时间:2013-07-23 14:58:58

标签: r cross-validation

我在R中有一个关于sapply的问题。在我的例子中,我用它进行留一交叉验证

 ##' Calculates the LOO CV score for given data and regression prediction function
##'
##' @param reg.data: regression data; data.frame with columns 'x', 'y'
##' @param reg.fcn:  regr.prediction function; arguments:
##'                    reg.x: regression x-values
##'                    reg.y: regression y-values
##'                    x:     x-value(s) of evaluation point(s)
##'                  value: prediction at point(s) x
##' @return LOOCV score
loocv <- function(reg.data, reg.fcn)
{
  ## Help function to calculate leave-one-out regression values
  loo.reg.value <- function(i, reg.data, reg.fcn)
    return(reg.fcn(reg.data$x[-i],reg.data$y[-i], reg.data$x[i]))

  ## Calculate LOO regression values using the help function above
  n <- nrow(reg.data)
  loo.values <- sapply(seq(1,n), loo.reg.value, reg.data, reg.fcn)

  ## Calculate and return MSE
  return(???)
}

我对sapply的疑问如下:

  1. 我可以使用多个参数和函数,即sapply(X1,FUN1,X2,FUN2,..),其中X1X2分别是函数FUN1FUN2的函数参数。
  2. 在上面的代码中,我将1:n应用于函数loo.reg.value。但是,此函数有多个参数,实际上是3:整数i,回归数据reg.data和回归函数reg.fcn。如果sapply中的函数有多个参数,并且我的X只涵盖其中一个参数,那么它是否会将其用作“第一个参数”?所以它与sapply(c(1:n,reg.data,reg.fcn),loo.reg.value, reg.data, reg.fcn)相同?
  3. 感谢您的帮助

2 个答案:

答案 0 :(得分:2)

在回答第一个问题时,可以使用多个函数,但需要将第二个和后续函数传递给第一个函数,然后传递给下一个函数等。因此需要对函数进行编码以便采用其他参数传递它们。

例如

foo <- function(x, f1, ...) f1(x, ...)
bar <- function(y, f2, ...) f2(y, ...)
foobar <- function(z, f3, ...) f3(z)

sapply(1:10, foo, f1 = bar, y = 2, f2 = foobar, z = 4, f3 = seq_len)

> sapply(1:10, foo, f1 = bar, y = 2, f2 = foobar, z = 4, f3 = seq_len)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    1    1    1    1    1    1    1    1     1
[2,]    2    2    2    2    2    2    2    2    2     2
[3,]    3    3    3    3    3    3    3    3    3     3
[4,]    4    4    4    4    4    4    4    4    4     4

这是一个愚蠢的例子,但它显示了如何将额外的参数传递给foo()最初,作为...的{​​{1}}参数的一部分。此外,它还演示了如何通过在函数定义和sapply()来使foo()和后续函数接受传递额外参数>如何调用下一个函数,例如...。注意我还避免了位置匹配的问题,并命名提供给f2(y, ...)的所有其他参数。

关于问题2,我认为你解释它的方式过于复杂。例如,您在使用foo()迭代的R中复制了reg.datareg.fcn位,这是不正确的(它意味着您迭代了向量中的3个内容{ {1}},而不是sapply())。

c(1:n,reg.data,reg.fcn)相当于

1:n

虽然sapply(1:n, fun, arg1, arg2)相当于

fun(1, arg1, arg2)
fun(2, arg1, arg2)
....
fun(10, arg1, arg2)

答案 1 :(得分:1)

您传递给sapply的函数可以根据您的需要获取尽可能多的参数(当然在理由之内),但它会回收除了每个应用程序的第一个参数之外的所有参数。你试过运行这段代码吗?看起来它会起作用。