如何概括外部到n维度?

kjo*_*kjo 8 reduce r vectorization outer-join

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

我想实现这个函数multi.outer,一个n维泛化outer:multi.outer(f, X_1, ..., X_n),其中f是一些n元函数,会产生一个(长度(X_1)*...*长度(X_n))数组,其中(i_1,... .,i_n)-th entry具有f(X_1[i_1], ..., X_n[i_n])所有有效索引集(i_1,...,i_n)的值.显然,对于每个i在{1,...,N},的所有元素X_imulti.outer(f, X_1,...,X_i,..., X_n)必须是可允许的第i个参数的函数f.对于n = 2的情况,multi.outer会做同样的事情outer,虽然它会有不同的签名(IOW,multi.outer(f, X, Y)相当于outer(X, Y, f)).

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

谢谢!

Pra*_*ani 16

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

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)
}
Run Code Online (Sandbox Code Playgroud)

现在,multi.outer只需要调用applydo.call对这个"ARGS矩阵":

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

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

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"
Run Code Online (Sandbox Code Playgroud)