我已经看过十几个网站可以学习申请,申请,lapply,但他们没有比教你如何获取行或列的总和或平均值更远的地方。我必须使用很多for循环,通常是嵌套的。请告诉我如何替换以下申请。
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
和
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
非常感谢任何回复。
答案 0 :(得分:5)
将循环转换为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)]
。我只是将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
现在让我们解决外循环。和以前一样,我们可以在函数中插入内容:
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_inner
内定义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)
}
或者,修改您的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))
}
要做的下一个修改是确保您想要返回一个值,而不是在函数内部进行赋值:
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
以及您的所有输入,我无法确保这正是您想要的。但我希望它能让你开始走上正确的道路!
编辑:我认为我为你的最终向量创建了错误的顺序:上面它会为i= 1
添加所有“j”值,然后为i = 2
添加所有“j”值。但是回头看看你的F
,看起来你想要的顺序是j=1
所有“i”值...要做到这一点,你只需要重新安排第二个lapply
的输出。 {1}}。这可行。
我想创建一个从列表中获取所有j
元素的函数:
LL <- lapply(1:NTR, foo_outer)
get_j_values <- function(j) {
sapply(LL, function(x) x[[j]])
}
对于任何j
值,get_j_value
会在向量中返回j
的所有LL
元素。通过将此函数应用于所有可能的j
值,它返回一个包含第一个元素的列表:j=1
的所有“i”值,然后是第二个元素j=2
的所有“i”值。 ..
LL2 <- lapply(1:NOUT, get_j_values)
然后我可以在一个大向量中折叠此列表并分配它。
F <- do.call(c, LL2)
编辑2:虽然可以使用apply
函数重新创建for循环,但这可能是for循环实际上更好的时候之一:没有积累结果所以{{ 1}}方法不应该更快,而且我认为for循环会更清晰。当您循环遍历多个不同对象的索引时,通常会出现这种情况,因此您不能直接在任何特定对象上使用apply
,但需要将函数应用于索引向量...只是我的两分钱......