R中的变量数量for循环

3

我正在使用R语言,希望将一个向量传递给函数。这个向量给出了一系列for循环的最大值。如果向量为(3,4,6,5),则应运行以下代码。所以,for循环的次数取决于传递到函数中的向量的长度。然后,对于每种可能性,计数器都被输入到另一个名为fn的函数中。下面提供了一个可能的fn函数示例。

S=0
fn = function(x){sum(x^2)}

for (i in 0:3){
   for (j in 0:4){
      for (k in 0:6){
         for (l in 0:5){
            S=S+fn(c(i,j,k,l))
       }
     }
   }
 }

我认为递归是解决这个问题的方法,但我一直没有找到解决方法,而且我看过的大多数递归示例似乎都处于非常高或非常低的级别。

你有什么建议来解决这个问题吗?

3个回答

7
不必使用循环
f <- function(vec, fn){
  vecs <- mapply(seq, 0, vec)
  tmp <- do.call(expand.grid, vecs)
  tmp <- apply(tmp, 1, fn)
  sum(tmp)
}

fn = function(x){sum(x^2)}
f(c(3, 4, 6, 5), fn = fn)

如果你想的话可以这样做。虽然它不符合OP的规定,需要更多的工作。它也只是将函数应用于整个扩展网格而不是逐行应用。在这种情况下它会给出相同的答案,但如果你对列进行不同的处理,它可能无法正常工作。 - Dason
谢谢,这非常有帮助。我应该提一下 - 向量可能相当长,向量中的值可能相当大。这是一个相对快速的解决方案还是可以通过某种方式改进? - user3666707
@user3666707 可能还有改进的空间。如果您的向量中有很多大数,那么由 expand.grid 创建的对象将会非常大。 - Dason

1

我喜欢@Dason使用expand.grid的版本,但是这里提供一种递归版本,用于那些可能无法使用该方法的情况或一般启示:

recfun <- function(a,b) {
    S <- 0
    if(length(b)) {
        for( i in seq(0,b[1]) ) {
            S <- S + Recall( c(a,i), b[-1] )
        }
    } else {
        return(fn(a))
    }
    S
}

recfun( numeric(0), c(3,4,6,5) )

为了实际应用,您可能希望将此包装在另一个函数中,该函数接受感兴趣的向量,并将其作为b传递给函数,同时使用空向量作为a


0

@Dason的回答非常好,但当vec的所有元素都相等时会失败(因为mapply然后将结果从列表转换为矩阵,而do.call需要一个列表)。这可以通过添加SIMPLIFY = FALSE来纠正:

class(mapply(seq, 0, c(2, 2)))
[1] "matrix"
class(mapply(seq, 0, c(2, 2), SIMPLIFY = FALSE))
[1] "list"

修改后的解决方案如下

f <- function(vec, fn){
  vecs <- mapply(seq, 0, vec, SIMPLIFY = FALSE)
  tmp <- do.call(expand.grid, vecs)
  tmp <- apply(tmp, 1, fn)
  sum(tmp)
}

fn = function(x){sum(x^2)}
f(c(3, 4, 6, 5), fn = fn)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接