向可怜的问题标题道歉。不太清楚如何在这里描述问题。
首先,我有以下代码。
# Data
set.seed(100)
x = matrix(runif(10000,0,1),100,100)
grpA = round(runif(100,1,5),0) # Group 1, 2, 3, 4, 5
# function
funA <-function(y, A){
X = lm(y~A)
return(X$residuals)
}
# Calculation
A = apply(x,1,function(y) funA(y,grpA))
现在,我没有使用grpA,而是使用grpB,每个列的组都不同。除了循环每一列,我还可以使用apply来计算吗?如果是这样,怎么样? 我的实际funA计算要复杂得多,我需要多次计算funA,所以我试图使用for循环进行aviod。谢谢。
grpB = matrix(round(runif(10000,1,5),0),100,100)
答案 0 :(得分:4)
首先,如果您的函数funA
做了大量工作,那么使用for
循环与apply
不会影响性能。这是因为唯一的区别在于循环的开销,并且在任何一种情况下大部分工作都将在funA
内进行。
事实上,即使funA
很简单,for
和apply
也不会有那么不同的表现。无论哪种方式,R内部都需要有一个带有多个R函数调用的循环。避免for
循环的真正性能改进来自于内置R函数,它通过在底层C代码中循环执行所需的计算而没有R中多个函数调用的开销。这是一个说明性示例
x<-matrix(runif(10000,0,1),100,100)
require(microbenchmark)
f1<-function(z){
ret<-rep(0,ncol(z))
for(i in 1:ncol(z)){
ret[i]<-sum(z[,i])
}
ret
}
f2<-function(z){
apply(z,2,sum)
}
identical(f1(x),f2(x))
# [1] TRUE
identical(f1(x),colSums(x))
# [1] TRUE
microbenchmark(f1(x),f2(x),colSums(x))
# unit: microseconds
# expr min lq median uq max neval
# f1(x) 559.934 581.4775 596.4645 622.1425 773.519 100
# f2(x) 484.265 512.1570 526.5700 546.5010 1100.540 100
# colSums(x) 23.844 25.7915 27.0675 28.7575 59.485 100
因此,在您的情况下,我不担心使用for
循环。有一些方法可以避免循环,例如
sapply(1:ncol(x),function(i) fun(x[,i],y[,i]))
但它不会比for循环快得多。
答案 1 :(得分:0)
您可以轻松地使用sequence
列数作为&#34;指标&#34;或者&#34;提取&#34;变量,并使用vapply
代替apply
,如下所示:
vapply(sequence(ncol(x)),
function(z) funA(x[, z], grpB[, z]),
numeric(nrow(x)))
答案 2 :(得分:0)
正如
的答案我还可以使用apply来计算吗?如果是这样,怎么样?
答案是肯定的。您可以将x
和grpB
合并到array
中,然后对结果数组使用apply。
# Data
set.seed(100)
x = matrix(runif(10000,0,1),100,100)
grpA = round(runif(100,1,5),0) # Group 1, 2, 3, 4, 5
# function
funA <-function(y, A){
X = lm(y~A)
return(X$residuals)
}
# Original calculation
A <- apply(x, 1, funA, grpA)
# the array in this case
arr <- array(c(x, matrix(rep(grpA, 100), nrow=100, byrow=TRUE)), dim=c(nrow(x), ncol(x), 2))
# the new calculation
res <- apply(arr, 1, function(y) funA(y[, 1], y[, 2]))
# comparing results
all.equal(A, res)
## TRUE
#
# and for the new groupB
grpB = matrix(round(runif(10000,1,5),0),100,100)
# the array
arr <- array(c(x, grpB), dim=c(nrow(x), ncol(x), 2))
# the calculation (same as above)
res <- apply(arr, 1, function(y) funA(y[, 1], y[, 2]))
请参阅@ mrip的答案,原因可能不是一个好主意。