我正在尝试(通过使用R)在基于两个输入向量的矩阵中构建“网格”。因此,我们的想法是避免这样的嵌套循环:
inputVector1=1:4
inputVector2=1:4
grid=NULL
for(i in inputVector1){
line=NULL
for(j in inputVector2){
cellValue=i+j # Instead of i+j it can be anything like taking a value in a dataframe
line=cbind(line,cellValue)
}
grid=rbind(grid,line)
}
R中是否有专用功能可以更快,更简单地完成这种工作?我知道有应用族功能,但是我没有找到合适的方法(没有组合多个应用族功能)。谢谢您的帮助。
答案 0 :(得分:2)
L.GUEGAN()
,以作进一步参考),您没有利用这样的事实:您知道最终网格的大小,并且一直在扩展向量,矩阵。那会使事情变慢。一个非常简单的替代方法是
niceFor <- function() {
grid <- matrix(0, nrow = length(inputVector1), ncol = length(inputVector2))
for(i in seq_along(inputVector1))
for(j in seq_along(inputVector2))
grid[i, j] <- i + j
grid
}
主要区别在于预定义网格对象并更新其值,而不是创建新对象。
outer(inputVector1, inputVector2, `+`)
但是,需要记住的是,第三个参数中的函数需要向量化,在这种情况下就是这种情况。也就是说,使用加法时可以使用向量
1:2 + 3:4
# [1] 4 6
`+`(1:2, 3:4)
# [1] 4 6
但是,其他一些功能未向量化。例如,
seq(3:4, 6:7)
# Error in seq.default(3:4, 6:7) : 'from' must be of length 1
在这种情况下,如果您使用outer
,请查看?Vectorize
。
grid[i, j] <- i * j
然后您应该使用
inputVector1 %*% t(inputVector2)
因为它比两个循环和outer
都更快,更干净。
microbenchmark(L.GUEGAN(), niceFor(), funOuter(), times = 2000)
# Unit: microseconds
# expr min lq mean median uq max neval cld
# L.GUEGAN() 24.354 33.8645 38.933968 35.6315 40.878 295.661 2000 c
# niceFor() 4.011 4.7820 6.576742 5.4050 7.697 29.547 2000 a
# funOuter() 4.928 6.1935 8.701545 7.3085 10.619 74.449 2000 b
因此,如果速度很重要,那么不错的for循环看起来甚至更好。请注意,您可以通过利用网格的对称性来进一步改进它:您可以手动计算仅矩阵的一半,然后使用结果填充另一个三角形。
答案 1 :(得分:0)
感谢@hrbrmstr,这是我一直在寻找的东西:
outer( 1:4, 1:4, function(a,b){mapply(FUN = function(x,y){return(x+y)},a,b)} )