基于两个输入向量构建网格

时间:2018-11-17 13:13:45

标签: r function

我正在尝试(通过使用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中是否有专用功能可以更快,更简单地完成这种工作?我知道有应用族功能,但是我没有找到合适的方法(没有组合多个应用族功能)。谢谢您的帮助。

2 个答案:

答案 0 :(得分:2)

  1. 循环 很简单,而且不一定慢。但是,这取决于如何使用这些循环。例如,在您的代码中(我将您的方法称为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
}

主要区别在于预定义网格对象并更新其值,而不是创建新对象。

  1. 是的,您可能会说它有专门的功能:

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

  1. 某些操作甚至具有“更直接”的专用功能。例如,如果我们有

grid[i, j] <- i * j

然后您应该使用

inputVector1 %*% t(inputVector2)

因为它比两个循环和outer都更快,更干净。

  1. 前面提到的三种方法的比较

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)} )