我在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
的疑问如下:
sapply(X1,FUN1,X2,FUN2,..)
,其中X1
和X2
分别是函数FUN1
和FUN2
的函数参数。 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)
相同? 感谢您的帮助
答案 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.data
和reg.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
的函数可以根据您的需要获取尽可能多的参数(当然在理由之内),但它会回收除了每个应用程序的第一个参数之外的所有参数。你试过运行这段代码吗?看起来它会起作用。