如何将外部推广到 n 维?
Posted
技术标签:
【中文标题】如何将外部推广到 n 维?【英文标题】:How to generalize outer to n dimensions? 【发布时间】:2011-09-05 18:38:53 【问题描述】:标准 R 表达式 outer(X, Y, f)
计算为一个矩阵,其第 (i, j) 项的值为 f(X[i], Y[j])
。
我想实现函数multi.outer
,outer
的 n 维泛化:multi.outer(f, X_1, ..., X_n)
,其中 f 是一些 n 元函数,将产生 (length(X_1) * ... * length(X_n)) 数组,其 (i_1,...,i_n)-th 条目对于所有有效索引集 (i_1,...,i_n) 具有值 f(X_1[i_1], ..., X_n[i_n])
。显然,对于 1, ..., n 中的每个 i,multi.outer(f, X_1,...,X_i,..., X_n)
中 X_i
的所有元素都必须是函数 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]
。
谢谢!
【问题讨论】:
【参考方案1】:我认为我们可以使用 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
此代码 sn-p 的唯一缺点是我使用默认值 a=-1:1 和 b=-1:1。当我尝试在函数调用期间传递相同的内容时,它会变得混乱。例如
sigm1(-1:1,-1:1,1:3)
[[1]]
[,1]
[1,] 0.1353353
[[2]]
[,1]
[1,] 1
[[3]]
[,1]
[1,] 54.59815
我无法弄清楚为什么传递参数会在输出中产生这种差异。
【讨论】:
【参考方案2】:这是一种方法:首先使用 Vectorize
和 outer
定义一个函数,该函数创建一个 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)
现在multi.outer
只需要在这个“args-matrix”上调用apply
和do.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"
【讨论】:
不错!在此处查看具有类似答案的类似(但不那么复杂)问题:***.com/questions/5233308/…【参考方案3】:这个怎么样:
multi.outer<-function(f,...)
apply(expand.grid(...),1,function(x)do.call(f,as.list(x)))
【讨论】:
我相信 OP 希望结果在一个 n 维矩阵中,每个维度对应于f
的每个参数。
+1 让我知道expand.grid
,但是当我尝试使用function (s, b, l) substr(s, b, b + l - 1)
测试功能multi.outer
(第一次)和c("ABCDEFGH", "IJKLMNOP", "QRSTUVWX"), 1:5, 2:3
作为其余部分时论点,我得到了Error in function (s, b, l) : unused argument(s) (Var1 = "ABCDEFGH", Var2 = "1", Var3 = "2")
。我还没有机会弄清楚你的实现是做什么的,或者为什么会出现这个错误。以上是关于如何将外部推广到 n 维?的主要内容,如果未能解决你的问题,请参考以下文章