如何概括外部到n维度?

时间:2011-05-31 19:58:59

标签: r vectorization reduce outer-join

标准R表达式outer(X, Y, f)求值为矩阵,其第(i,j)个条目的值为f(X[i], Y[j])

我想实现函数multi.outeroutermulti.outer(f, X_1, ..., X_n)的n维泛化,其中f是一些n元函数,会产生一个(长度(X_1) )* ... * length(X_n))数组,其(i_1,...,i_n)条目对于所有有效索引集(i_1,...,i_n)具有值f(X_1[i_1], ..., X_n[i_n])。显然,对于{1,...,n}中的每个i,X_imulti.outer(f, X_1,...,X_i,..., X_n)的所有元素必须是函数f的第i个参数。对于n = 2的情况,multi.outer将与outer做同样的事情,尽管它会有不同的签名(IOW,multi.outer(f, X, Y)等同于outer(X, Y, f))。

重要的是要注意,尽管multi.outer的参数X_1,...,X_n都是向量,但它们并不一定都具有相同的模式。例如。 X_1和X_2可分别为c(1, 2, 3)LETTERS[10:20]

谢谢!

3 个答案:

答案 0 :(得分:16)

这是一种方法:首先使用Vectorizeouter来定义一个创建n维矩阵的函数,其中每个条目都是应用给定函数的参数列表: / p>

list_args <- Vectorize( function(a,b) c( as.list(a), as.list(b) ), 
                        SIMPLIFY = FALSE)


make_args_mtx <- function( alist ) {
  Reduce(function(x, y) outer(x, y, list_args), alist)
}

现在multi.outer只需要在此“args-matrix”上调用applydo.call

multi.outer <- function(f, ... ) {
  args <- make_args_mtx(list(...))
  apply(args, 1:length(dim(args)), function(a) do.call(f, a[[1]] ) )
}

让我们用一个示例函数来尝试:

fun <- function(a,b,c) paste(a,b,c)

ans <- multi.outer(fun, LETTERS[1:2], c(3, 4, 5), letters[6:7] )

> ans
, , 1

     [,1]    [,2]    [,3]   
[1,] "A 3 f" "A 4 f" "A 5 f"
[2,] "B 3 f" "B 4 f" "B 5 f"

, , 2

     [,1]    [,2]    [,3]   
[1,] "A 3 g" "A 4 g" "A 5 g"
[2,] "B 3 g" "B 4 g" "B 5 g"

答案 1 :(得分:1)

这个怎么样:


multi.outer<-function(f,...){

  apply(expand.grid(...),1,function(x){do.call(f,as.list(x))})

}

答案 2 :(得分:0)

我认为我们可以使用Outer和Vectorize来做到这一点。

 sigm = function(a=0,b=0,x){
 return(exp(x*a+b))
 }

 sigm1 = Vectorize(function(a=-1:1,b=-1:1,x){

 outer(a,b,sigm,x)
 },SIMPLIFY = FALSE)

现在,sigm1(x = 1:3)给出了所需的输出

 [[1]]
      [,1]      [,2]     [,3]
 [1,] 0.1353353 0.3678794 1.000000
 [2,] 0.3678794 1.0000000 2.718282
 [3,] 1.0000000 2.7182818 7.389056

[[2]]
       [,1]      [,2]       [,3]
[1,] 0.04978707 0.1353353  0.3678794
[2,] 0.36787944 1.0000000  2.7182818
[3,] 2.71828183 7.3890561 20.0855369

[[3]]
       [,1]        [,2]       [,3]
[1,] 0.01831564  0.04978707  0.1353353
[2,] 0.36787944  1.00000000  2.7182818
[3,] 7.38905610 20.08553692 54.5981500

使用此代码段的唯一回退是我使用的默认值为a = -1:1和b = -1:1。当我在函数调用期间尝试传递相同内容时,它会变得混乱。 E.g。

sigm1(-1:1,-1:1,1:3)

[[1]]
      [,1]
[1,] 0.1353353

[[2]]
 [,1]
[1,]    1

[[3]]
     [,1]
[1,] 54.59815

我无法弄清楚为什么传递参数会使输出产生差异。