在 R 中,我们有一个数组和一个矩阵:
a <- array(rep(1:3, each = 4), dim = c(2, 2, 3))
b <- matrix(seq(0, 1, length.out = 6), nrow = 2, ncol = 3)
我想使用一个函数,该函数利用
a
沿第三维的矩阵和 b
中的列作为其两个参数。对于这个例子,我们可以假设我的函数是:
myfunc <- function(x, y) { x * y }
我希望该操作返回一个 3D 数组。我当前的解决方案是使用
sapply
作为索引,然后将结果列表转换为数组:
res <- sapply(1:dim(a)[[3]], FUN = \(x) myfunc(a[, , x], b[, x]), simplify = FALSE)
res <- abind::abind(res, along = 3)
是否有另一种方法可以实现直接生成 3D 数组的操作?我尝试过
sweep
,但失败了。
一种可能的方法是将 3D 数组和矩阵更改为列表并使用
mapply
。在这里,我编写了一个简单的函数(to_list()
),它执行数组到列表的转换(默认情况下沿着最后一个数组维度)。
to_list <- function(x, along=length(dim(x))) {
apply(x, along, identity, simplify=F)
}
res <- mapply(myfunc, to_list(b), to_list(a), SIMPLIFY=F)
res <- sapply(res, identity, simplify='array')
sapply
线与您的 abind
线执行相同的操作。
我们可以使用
aperm
转置多维数组。
f <- \(A, m) aperm(aperm(A, c(3, 2, 1))*as.vector(t(m)), c(2, 3, 1))
f(a, b)
# , , 1
#
# [,1] [,2]
# [1,] 0.0 0.0
# [2,] 0.2 0.2
#
# , , 2
#
# [,1] [,2]
# [1,] 0.8 0.8
# [2,] 1.2 1.2
#
# , , 3
#
# [,1] [,2]
# [1,] 2.4 2.4
# [2,] 3.0 3.0
stopifnot(all.equal(res, f(a, b), check.attributes=FALSE)) ## res from OP