use*_*024 -1 for-loop r apply nested-loops
我已经看到了十二个要学习应用,应用,应用的站点,但是它们没有比教您如何获取行或列的总和或平均值更有效的方法。我必须使用很多for循环,通常是嵌套的。请在下面说明如何用Apply替换。
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
for (j in 1:NOUT) {
F[i+NOUT*(j-1)] = Y[j]-YTR[i,j]
} # j
} # i
Run Code Online (Sandbox Code Playgroud)
和
for (k in 1:NOUT) {
for (iwt in 1:NWT) {
m = NHID*(NNLIN+1)
if (iwt <= m) {
i = (iwt-1) %/% (NNLIN+1) + 1
j = (iwt-1) %% (NNLIN+1)
EVZ = V[k,i+1]*Z[i]*(1-Z[i])
if (j>0) EVZ = EVZ*X[j]
J[k+(n-1)*NOUT,iwt] = EVZ
}
} # iwt
} # k
Run Code Online (Sandbox Code Playgroud)
非常感谢您的任何答复。
将循环转换为延迟的最简单方法是获取for循环中的内容并将其插入函数中。让我们从您的内循环开始。
foo_inner <- function(j) {
F[i+NOUT*(j-1)] = Y[j]-YTR[i,j]
}
Run Code Online (Sandbox Code Playgroud)
但是这里有一个问题:您的函数应该返回一个值而不是赋值。在这种情况下,您想返回Y[j]-YTR[i,j]。
foo_inner <- function(j) {
return(Y[j]-YTR[i,j])
}
Run Code Online (Sandbox Code Playgroud)
然后,您只需将此功能应用于即可1:NOUT。在这种情况下,(虽然我不能确定您的帖子中缺少信息),但此返回值只是一个数字,因此您可以直接创建矢量而不是列表。在这种情况下,最好使用sapply而不是lapply(“ s”代表简化(表示向量),而“ l”代表列表):
sapply(1:NOUT, foo_inner)
Run Code Online (Sandbox Code Playgroud)
现在必须在您的外部循环中分配此新向量。从您的代码看来,您想要将此向量分配给F[i+NOUT*(1:NOUT-1)]。我只是用您的迭代器替换了您的j值1:NOUT。因此,您的代码段可以像下面这样修改:
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
Run Code Online (Sandbox Code Playgroud)
现在让我们解决外部循环。和以前一样,我们可以插入函数中的内容:
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)
}
Run Code Online (Sandbox Code Playgroud)
这里有两个需要克服的问题:首先,您的foo_inner函数以i参数为参数。但是,foo_inner在外部进行定义时foo_outer,它将始终使用i您的环境中定义的内容,而不是的参数foo_outer。有两种解决方案:要么foo_inner在inside 中定义foo_outer:
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)
}
Run Code Online (Sandbox Code Playgroud)
或者,修改foo_inner函数,使其以i参数为参数并返回正确的函数。然后,您将foo_inner(i)在内部sapply而不是在内部应用函数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))
}
Run Code Online (Sandbox Code Playgroud)
接下来要做的修改是确保您要返回一个值,而不是在函数内部进行赋值:
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)))
}
Run Code Online (Sandbox Code Playgroud)
您现在可以应用此功能:
lapply(1:NTR, foo_outer)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我使用了一个,lapply因为返回的每个元素都是一个向量,所以我宁愿返回一个列表并将其折叠起来,因为我不确定sapply在这种情况下是否会这样做(而且太懒了,无法找到此刻,如果有人可以确认,我会纠正)。
所以您现在想要一个大向量,所以我将全部折叠。
do.call(c, lapply(1:NTR, foo_outer))
Run Code Online (Sandbox Code Playgroud)
然后,我可以F直接将此值分配给:
F <- do.call(c, lapply(1:NTR, foo_outer))
Run Code Online (Sandbox Code Playgroud)
显然,如果不知道,和所有输入内容F,就无法确保这正是您想要的。但我希望它能使您走上正确的道路!YTRY
编辑:我想我为您的最终向量创建了错误的顺序:通过上述操作,它将放所有的“ j”值,i= 1然后放所有的“ j”值i = 2...但是回头看,您F的顺序看起来像您want是j=1所有“ i”值的...为此,您只需要重新排列第二个输出lapply。这行得通。
我想创建一个j将从列表中获取所有元素的函数:
LL <- lapply(1:NTR, foo_outer)
get_j_values <- function(j) {
sapply(LL, function(x) x[[j]])
}
Run Code Online (Sandbox Code Playgroud)
对于任何j值,均get_j_value在向量中返回的所有j元素LL。通过将此函数应用于所有可能的j值,它将返回包含第一个元素的列表:j=1第二个元素的所有“ i”值,然后第二个元素的所有“ i”值j=2...
LL2 <- lapply(1:NOUT, get_j_values)
Run Code Online (Sandbox Code Playgroud)
然后,我可以将此列表折叠到一个大向量中并进行分配。
F <- do.call(c, LL2)
Run Code Online (Sandbox Code Playgroud)
编辑2:尽管可以使用apply函数来重新创建for循环,但这可能是其中一次for循环实际上更好的情况之一:没有结果的累积,因此该apply方法不应该更快并且for循环我相信会更清楚。当您遍历在多个不同对象上使用的索引时,通常是这种情况,这样您就不能apply直接在任何特定对象上使用on,而是需要将函数应用于索引向量...仅需两美分。 ..