沿数组第 3 维的子集应用总和
apply sum along subsets of array 3rd dimension
我有以下对象:
A:1 个具有 x、y、z 维度的数组 -> 包含一个变量(温度)
B & C:2 个 x、y 维度的数组 -> 包含沿 A 的 z 维度的向量索引
A <- array(rnorm(n = 12*4*3*5), dim = c(4,3,5))
dimnames(A) <- list("x" = c(1:4), "y" = c(1:3), "z" = c(1:5))
B <- matrix(rep(c(2:1), 6), nrow = 4)
dimnames(B) <- list("x" = c(1:4), "y" = c(1:3))
C <- matrix(rep(c(4:5), 6), nrow = 4)
dimnames(C) <- list("x" = c(1:4), "y" = c(1:3))
我正在寻找一种方法,仅在 B 和 C 指示的索引之间应用跨 z 维度的 A 之和。
如果我有一个向量而不是 3D 数组,我会这样解决它:
> A <- round(c(rnorm(5)), 1)
> B <- 2 #index of first value to sum
> C <- 4 #index of last value to sum
> vindex <- seq(B,C,1)
> A
[1] 0.0 -0.9 -1.1 -1.7 -0.4
> vindex
[1] 2 3 4
> sum(A[vindex])
[1] -3.7
>
# or better with a function
> foo <- function(x, start_idx, end_idx) {
+ vidx <- seq(start_idx, end_idx, 1)
+ return(sum(x[vidx]))
+ }
>
> foo(A,B,C)
[1] -3.7
不幸的是,seq() 不接受向量作为参数,因此使用 apply 函数并不简单。如果又是 A[x,y,z] 和 B 和 C[x,y]:
> apply(A,c(1,2),foo,B,C)
Error in seq.default(start_idx, end_idx, 1) : 'from' must be of length 1
Called from: seq.default(start_idx, end_idx, 1)
如果有人知道如何使用 apply 或其他干净的解决方案使此功能可用,那就太好了。
非常感谢!
这对于基础 R 来说不是一个很好的任务,在没有已经这样做的包的情况下,我更愿意在 C++ 中实现它 (?)。
从逻辑上讲,针对您的问题的简单但矢量化的解决方案可以构造为:
# initialize index array
D <- array(
1,
dim = c(4,3,5),
dimnames = list(x = letters[1:4], y = letters[1:3], z = letters[1:5])
)
# set indices out of bounds to zero
E <- rep(1:5, each = 4*3)
BB <- rep(B, times = 5)
D[E < BB] <- 0
CC <- rep(C, times = 5)
D[E > CC] <- 0
# multiply with index array and sum
apply(A * D, c(1,2), sum)
我有以下对象:
A:1 个具有 x、y、z 维度的数组 -> 包含一个变量(温度)
B & C:2 个 x、y 维度的数组 -> 包含沿 A 的 z 维度的向量索引
A <- array(rnorm(n = 12*4*3*5), dim = c(4,3,5))
dimnames(A) <- list("x" = c(1:4), "y" = c(1:3), "z" = c(1:5))
B <- matrix(rep(c(2:1), 6), nrow = 4)
dimnames(B) <- list("x" = c(1:4), "y" = c(1:3))
C <- matrix(rep(c(4:5), 6), nrow = 4)
dimnames(C) <- list("x" = c(1:4), "y" = c(1:3))
我正在寻找一种方法,仅在 B 和 C 指示的索引之间应用跨 z 维度的 A 之和。
如果我有一个向量而不是 3D 数组,我会这样解决它:
> A <- round(c(rnorm(5)), 1)
> B <- 2 #index of first value to sum
> C <- 4 #index of last value to sum
> vindex <- seq(B,C,1)
> A
[1] 0.0 -0.9 -1.1 -1.7 -0.4
> vindex
[1] 2 3 4
> sum(A[vindex])
[1] -3.7
>
# or better with a function
> foo <- function(x, start_idx, end_idx) {
+ vidx <- seq(start_idx, end_idx, 1)
+ return(sum(x[vidx]))
+ }
>
> foo(A,B,C)
[1] -3.7
不幸的是,seq() 不接受向量作为参数,因此使用 apply 函数并不简单。如果又是 A[x,y,z] 和 B 和 C[x,y]:
> apply(A,c(1,2),foo,B,C)
Error in seq.default(start_idx, end_idx, 1) : 'from' must be of length 1
Called from: seq.default(start_idx, end_idx, 1)
如果有人知道如何使用 apply 或其他干净的解决方案使此功能可用,那就太好了。
非常感谢!
这对于基础 R 来说不是一个很好的任务,在没有已经这样做的包的情况下,我更愿意在 C++ 中实现它 (?)。
从逻辑上讲,针对您的问题的简单但矢量化的解决方案可以构造为:
# initialize index array
D <- array(
1,
dim = c(4,3,5),
dimnames = list(x = letters[1:4], y = letters[1:3], z = letters[1:5])
)
# set indices out of bounds to zero
E <- rep(1:5, each = 4*3)
BB <- rep(B, times = 5)
D[E < BB] <- 0
CC <- rep(C, times = 5)
D[E > CC] <- 0
# multiply with index array and sum
apply(A * D, c(1,2), sum)