将循环转换为 lapply 的最简单方法是将 for 循环中的内容插入函数中。让我们从你的内部循环开始。
foo_inner <- function(j) {
F[i+NOUT*(j-1)] = Y[j]-YTR[i,j]
}
这里有一个问题:你的函数应该返回一个值而不是分配它。在这种情况下,您想返回Y[j]-YTR[i,j]。
foo_inner <- function(j) {
return(Y[j]-YTR[i,j])
}
然后您可以简单地将这个函数应用于1:NOUT。在这种情况下,似乎(尽管我无法确定您的帖子中缺少信息)此返回值只是一个数字,因此您可以直接创建向量而不是列表。在这种情况下,最好使用sapply 而不是lapply('s' 表示简化(到向量),而'l' 表示列表):
sapply(1:NOUT, foo_inner)
现在必须在您的外循环中分配这个新向量。从您的代码中,您似乎想将此向量分配给F[i+NOUT*(1:NOUT-1)]。我只是用 1:NOUT 替换了您的 j 值,这是您的迭代器。因此,您的代码 sn-p 可以这样修改:
for (i in 1:NTR) {
X = as.vector(as.matrix(XTR[i,]))
YZ = FN(W, V, U, X) # return Y and Z
Y = YZ$Y
Z = YZ$Z
F[i+NOUT*(1:NOUT-1)] <- sapply(1:NOUT, foo_inner)
} # i
现在让我们处理外循环。和以前一样,我们可以将里面的内容插入一个函数中:
foo_outer <- function(i) {
X = as.vector(as.matrix(XTR[i,]))
YZ = FN(W, V, U, X) # return Y and Z
Y = YZ$Y
Z = YZ$Z
F[i+NOUT*(1:NOUT-1)] <- sapply(1:NOUT, foo_inner)
}
这里有两个问题需要克服:首先,您的foo_inner 函数将i 作为参数。但是,foo_inner 在foo_outer 之外定义,它将始终使用在您的环境中定义的i,而不是foo_outer 的参数。有两种解决方案:要么在 foo_outer 内定义 foo_inner:
foo_outer <- function(i) {
X = as.vector(as.matrix(XTR[i,]))
YZ = FN(W, V, U, X) # return Y and Z
Y = YZ$Y
Z = YZ$Z
foo_inner <- function(j) {
return(Y[j]-YTR[i,j])
}
F[i+NOUT*(1:NOUT-1)] <- sapply(1:NOUT, foo_inner)
}
或者,修改您的foo_inner 函数,使其将i 作为参数并返回正确的函数。然后,您将在内部 sapply 中应用函数 foo_inner(i) 而不是 foo_inner:
foo_inner <- function(i) {
function(j) {
return(Y[j]-YTR[i,j])
}
}
foo_outer <- function(i) {
X = as.vector(as.matrix(XTR[i,]))
YZ = FN(W, V, U, X) # return Y and Z
Y = YZ$Y
Z = YZ$Z
F[i+NOUT*(1:NOUT-1)] <- sapply(1:NOUT, foo_inner(i))
}
接下来要做的修改是确保您想要返回一个值,而不是在函数内部进行赋值:
foo_inner <- function(i) {
function(j) {
return(Y[j]-YTR[i,j])
}
}
foo_outer <- function(i) {
X = as.vector(as.matrix(XTR[i,]))
YZ = FN(W, V, U, X) # return Y and Z
Y = YZ$Y
Z = YZ$Z
return(sapply(1:NOUT, foo_inner(i)))
}
您现在可以应用此功能:
lapply(1:NTR, foo_outer)
在这种情况下,我使用了lapply,因为返回的每个元素都是一个向量,所以我宁愿返回一个列表并在之后折叠它,因为我不确定sapply 在这种情况下是否这样做(暂时懒得去查,如果有人能确认我会更正)。
所以你现在想要一个大向量,所以我将把它全部折叠起来。
do.call(c, lapply(1:NTR, foo_outer))
然后我可以直接将此值分配给F:
F <- do.call(c, lapply(1:NTR, foo_outer))
显然,如果不知道 F、YTR、Y 以及您的所有输入是什么,我无法确保这正是您想要的。但我希望它能让你走上正确的道路!
编辑:我认为我为您的最终向量创建了错误的顺序:使用上面的内容,它会将所有“j”值放入 i= 1,然后将所有“j”值放入 i = 2... 但回头看在您的F,看起来您想要的顺序是j=1 所有“i”值...为此,您只需重新排列第二个lapply 的输出。这应该可行。
我想创建一个从列表中获取所有j 元素的函数:
LL <- lapply(1:NTR, foo_outer)
get_j_values <- function(j) {
sapply(LL, function(x) x[[j]])
}
对于任何j 值,get_j_value 在向量中返回LL 的所有jth 元素。通过将此函数应用于所有可能的 j 值,它会返回一个包含第一个元素的列表:j=1 的所有“i”值然后对于第二个元素,j=2 的所有“i”值...
LL2 <- lapply(1:NOUT, get_j_values)
然后我可以将这个列表折叠成一个大向量并分配它。
F <- do.call(c, LL2)
编辑 2:虽然可以使用 apply 函数来重新创建你的 for 循环,但这可能是 for 循环实际上更好的时候之一:没有结果的累积,所以 apply 方法不应该更快,我相信 for 循环会更清晰。当您循环使用多个不同对象的索引时,通常会出现这种情况,因此您不能直接在任何特定对象上使用apply,但需要将函数应用于索引向量......只是我的两美分...