【问题标题】:Generating an n-dimensional array by applying function to all pairs通过将函数应用于所有对来生成 n 维数组
【发布时间】:2017-04-12 17:52:19
【问题描述】:

F 成为一个函数,它接受两个参数并为某个整数返回一个数字 k-向量(即长度为 k 的数字向量) k > 1,并让XY 成为适合作为F 的第一个和第二个参数(分别)的值的向量。

是否有一种“功能性”(即无循环)且方便的方式来生成 3 维数组 A,这样,对于所有合适的 ij,以下表达式为 @987654328 @?

all.equal(A[i, j, ], F(X[[i]], Y[[j]]))

更一般地说,让F 是一个函数,它接受两个参数并返回一个数字 n 维数组(其中,dim(F(x, y)) = D 是一个常量 n-向量,对于所有有效参数 xy),并且像以前一样,让 XY 是适合作为 F 的第一个和第二个参数(分别)的值的向量。

是否有一种“功能性”(即无循环)且方便的方法来生成 (n + 2) 维数组 A(其中 dim(A) 等于 @987654339 @) 这样,对于所有合适的ij,以下表达式为TRUE?

all.equal(A[i, j, , ... , ], F(X[[i]], Y[[j]]))

AFAICT,outer 不适用于此。例如,假设F 是这样定义的:

F <- function (m, n) {
    set.seed(m - n);
    array(runif(6), dim = c(3, 2))
}

这个F 接受两个整数作为参数,并返回一个 3 × 2 浮点数数组。例如:

F(3, 8)
          [,1]      [,2]
[1,] 0.7345948 0.6368477
[2,] 0.3396928 0.9620946
[3,] 0.1910453 0.3756567

但是

outer(1:3, 1:3, Vectorize(F))
Error in outer(1:3, 1:3, Vectorize(F)) : 
  dims [product 9] do not match the length of object [54]

我认为outer 在这里不起作用的原因是因为(强调)

外部(X, Y, FUN = "*", ...)

...

'FUN' 以这两个扩展向量作为参数调用(加上 '...' 中的任何参数)。它必须是矢量化函数(或 一个的名称)期望至少有两个参数并且返回一个 与第一个(和第二个)长度相同的值


Vlo 更新:

## the line below is cut-and-paste'd directly from comment
F<-function(m,n){set.seed(m - n);list(array(runif(6), dim = c(3, 2)))}; x = outer(1:3, 1:5, Vectorize(F, "m", "n"))

如果我现在检查 x,我会得到: x

     [,1]      [,2]      [,3]      [,4]      [,5]     
[1,] Numeric,6 Numeric,6 Numeric,6 Numeric,6 Numeric,6
[2,] Numeric,6 Numeric,6 Numeric,6 Numeric,6 Numeric,6
[3,] Numeric,6 Numeric,6 Numeric,6 Numeric,6 Numeric,6

这不是我要找的。一方面,这里的dim(x) 等于向量c(3, 5),而对于所需的x,它应该是那个

dim(x)
[1] 3 5 3 2

for (i in 1:3) {
    for (j in 1:5) {
        cat('\n', paste(c(i, j, '', ''), collapse = ', '), '\n')
        print(x[i, j, ,])
    }
}
 1, 1, ,  
          [,1]      [,2]
[1,] 0.8966972 0.5728534
[2,] 0.2655087 0.9082078
[3,] 0.3721239 0.2016819

 1, 2, ,  
          [,1]      [,2]
[1,] 0.4866672 0.1467027
[2,] 0.1913653 0.2415895
[3,] 0.9932719 0.5371012

 1, 3, ,  
          [,1]      [,2]
[1,] 0.8141134 0.2416691
[2,] 0.5890751 0.9928682
[3,] 0.1339374 0.9844079

 1, 4, ,  
          [,1]      [,2]
[1,] 0.7705233 0.3878055
[2,] 0.7820377 0.1221871
[3,] 0.3802074 0.3378332

 1, 5, ,  
           [,1]      [,2]
[1,] 0.38668404 0.7800617
[2,] 0.09064471 0.4887107
[3,] 0.65027437 0.9742584

 2, 1, ,  
          [,1]      [,2]
[1,] 0.2655087 0.9082078
[2,] 0.3721239 0.2016819
[3,] 0.5728534 0.8983897

 2, 2, ,  
          [,1]      [,2]
[1,] 0.8966972 0.5728534
[2,] 0.2655087 0.9082078
[3,] 0.3721239 0.2016819

 2, 3, ,  
          [,1]      [,2]
[1,] 0.4866672 0.1467027
[2,] 0.1913653 0.2415895
[3,] 0.9932719 0.5371012

 2, 4, ,  
          [,1]      [,2]
[1,] 0.8141134 0.2416691
[2,] 0.5890751 0.9928682
[3,] 0.1339374 0.9844079

 2, 5, ,  
          [,1]      [,2]
[1,] 0.7705233 0.3878055
[2,] 0.7820377 0.1221871
[3,] 0.3802074 0.3378332

 3, 1, ,  
          [,1]      [,2]
[1,] 0.1848823 0.1680519
[2,] 0.7023740 0.9438393
[3,] 0.5733263 0.9434750

 3, 2, ,  
          [,1]      [,2]
[1,] 0.2655087 0.9082078
[2,] 0.3721239 0.2016819
[3,] 0.5728534 0.8983897

 3, 3, ,  
          [,1]      [,2]
[1,] 0.8966972 0.5728534
[2,] 0.2655087 0.9082078
[3,] 0.3721239 0.2016819

 3, 4, ,  
          [,1]      [,2]
[1,] 0.4866672 0.1467027
[2,] 0.1913653 0.2415895
[3,] 0.9932719 0.5371012

 3, 5, ,  
          [,1]      [,2]
[1,] 0.8141134 0.2416691
[2,] 0.5890751 0.9928682
[3,] 0.1339374 0.9844079

【问题讨论】:

  • 这真的取决于细节以及“无循环”的含义。如果将向量(而不是单个值)传递给F 的任一参数,会发生什么情况?你能调整F 使其能够处理矢量化吗?最终,F 做了什么?无论如何,你可以通过expand.gridmapply 的组合来实现你想要的,但几乎不能定义为loop-free
  • 我不完全明白你在追求什么,但它听起来像是mapply 的工作。至少第一部分可以。
  • F&lt;-function(m,n){set.seed(m - n);list(array(runif(6), dim = c(3, 2)))}; x = outer(1:3, 1:5, Vectorize(F, "m", "n")) 有效。 Vectorize 只是一个很大的旧循环。
  • @Frank:对此感到抱歉(已修复)。
  • @Vlo:您发布的 sn-p 不会产生正确的结果。 (在我对问题的回答中,我举了一个期望输出的例子。)

标签: r multidimensional-array


【解决方案1】:

好的,这是一个笨拙的解决方案。 我发布它是希望它能从比我更好地掌握 R 的人那里引出一个更好的人

outer_nd <- function(x, y, f) {
    pairs <- unname(as.matrix(expand.grid(x, y)))
    n <- nrow(pairs)
    rows <- split(pairs, seq(n))
    values <- sapply(rows, function (p) do.call(f, as.list(p)))
    array(t(values), dim = c(length(x), length(y), dim(F(x[[1]], y[[1]]))))
}

这个解决方案至少明确地显示了我所追求的。

例如,如果F 是这样定义的

F <- function (m, n) {
    set.seed(m - n);
    array(runif(6), dim = c(3, 2))
}

...然后

z <- outer_nd(1:2, 1:2, F)
dim(z)
 [1] 2 2 3 2

for (i in 1:2) {
    for (j in 1:2) {
        cat('\n', paste(c(i, j, '', ''), collapse = ', '), '\n')
        print(z[i, j, ,])

        cat('\nF(', paste(c(i, j), collapse = ', '), ') =\n')
        print(F(i, j))
        cat('\n')
    }
}
 1, 1, ,  
          [,1]      [,2]
[1,] 0.8966972 0.5728534
[2,] 0.2655087 0.9082078
[3,] 0.3721239 0.2016819

F( 1, 1 ) =
          [,1]      [,2]
[1,] 0.8966972 0.5728534
[2,] 0.2655087 0.9082078
[3,] 0.3721239 0.2016819


 1, 2, ,  
          [,1]      [,2]
[1,] 0.4866672 0.1467027
[2,] 0.1913653 0.2415895
[3,] 0.9932719 0.5371012

F( 1, 2 ) =
          [,1]      [,2]
[1,] 0.4866672 0.1467027
[2,] 0.1913653 0.2415895
[3,] 0.9932719 0.5371012


 2, 1, ,  
          [,1]      [,2]
[1,] 0.2655087 0.9082078
[2,] 0.3721239 0.2016819
[3,] 0.5728534 0.8983897

F( 2, 1 ) =
          [,1]      [,2]
[1,] 0.2655087 0.9082078
[2,] 0.3721239 0.2016819
[3,] 0.5728534 0.8983897


 2, 2, ,  
          [,1]      [,2]
[1,] 0.8966972 0.5728534
[2,] 0.2655087 0.9082078
[3,] 0.3721239 0.2016819

F( 2, 2 ) =
          [,1]      [,2]
[1,] 0.8966972 0.5728534
[2,] 0.2655087 0.9082078
[3,] 0.3721239 0.2016819

【讨论】:

    猜你喜欢
    • 2014-04-29
    • 2010-12-19
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    • 1970-01-01
    相关资源
    最近更新 更多