14

我在 R 中有一个数组,由这样的函数创建:

A <- array(data=NA, dim=c(2,4,4), dimnames=list(c("x","y"),NULL,NULL))

我想选择一维,所以对于上面的例子,我会有:

A["x",,]
dim(A["x",,])    #[1] 4 4

如果我事先不知道我的数组可能有多少维(除了我要选择的命名维),有没有一种方法可以概括?我想编写一个函数,该函数接受可能格式化为上述 A 的输入,或者:

B <- c(1,2)
names(B) <- c("x", "y")

C <- matrix(1, 2, 2, dimnames=list(c("x","y"),NULL))

背景

一般背景是我正在研究 ODE 模型,因此对于 deSolve 的 ODE 函数,它必须采用我当前状态的单个命名向量。对于其他一些函数,比如计算相平面/方向场,有一个更高维的数组来应用微分方程会更实用,而且我想避免拥有相同函数的多个副本,只是使用不同的我要选择的维度后的逗号数。

4

4 回答 4

11

我花了很多时间为 plyr 找出最快的方法,而我能想到的最好的方法是手动构建对以下的调用[

index_array <- function(x, dim, value, drop = FALSE) { 
  # Create list representing arguments supplied to [
  # bquote() creates an object corresponding to a missing argument
  indices <- rep(list(bquote()), length(dim(x)))
  indices[[dim]] <- value

  # Generate the call to [
  call <- as.call(c(
    list(as.name("["), quote(x)),
    indices,
    list(drop = drop)))
  # Print it, just to make it easier to see what's going on
  print(call)

  # Finally, evaluate it
  eval(call)
}

(您可以在https://github.com/hadley/devtools/wiki/Computing-on-the-language找到有关此技术的更多信息)

然后,您可以按如下方式使用它:

A <- array(data=NA, dim=c(2,4,4), dimnames=list(c("x","y"),NULL,NULL))
index_array(A, 2, 2)
index_array(A, 2, 2, drop = TRUE)
index_array(A, 3, 2, drop = TRUE)

如果您想基于多个维度进行提取,它也会以一种直接的方式进行概括,但您需要重新考虑函数的参数。

于 2013-01-24T13:19:29.120 回答
5

我写了这个通用函数。不一定超快,但arrayInd矩阵索引的一个很好的应用程序:

extract <- function(A, .dim, .value) {

    val.idx  <- match(.value, dimnames(A)[[.dim]])
    all.idx  <- arrayInd(seq_along(A), dim(A))
    keep.idx <- all.idx[all.idx[, .dim] == val.idx, , drop = FALSE]
    array(A[keep.idx], dim = dim(A)[-.dim], dimnames = dimnames(A)[-.dim])

}

例子:

A <- array(data=1:32, dim=c(2,4,4),
           dimnames=list(c("x","y"), LETTERS[1:4], letters[1:4]))

extract(A, 1, "x")
extract(A, 2, "D")
extract(A, 3, "b")
于 2013-01-24T12:32:20.287 回答
2

也许有一种更简单的方法,但这有效:

do.call("[",c(list(A,"x"),lapply(dim(A)[-1],seq)))
     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA
[4,]   NA   NA   NA   NA

让我们将其概括为一个可以从任何维度提取的函数,不一定是第一个:

extract <- function(A, .dim, .value) {
    idx.list <- lapply(dim(A), seq_len)
    idx.list[[.dim]] <- .value
    do.call(`[`, c(list(A), idx.list))
}

例子:

A <- array(data=1:32, dim=c(2,4,4),
           dimnames=list(c("x","y"), LETTERS[1:4], letters[1:4]))

extract(A, 1, "x")
extract(A, 2, "D")
extract(A, 3, "b")
于 2013-01-24T12:20:25.487 回答
2

除了其他非常有用的数组操作函数之外, abind 包还有一个函数 , 来执行此操作asub

library(abind)
A <- array(data=1:32, dim=c(2,4,4),
           dimnames=list(c("x","y"), LETTERS[1:4], letters[1:4]))

asub(A, 'x', 1)
asub(A, 'D', 2)
asub(A, 'b', 3)

它允许在多个维度上建立索引:

asub(A, list('x', c('C', 'D')), c(1,2))
于 2017-09-19T23:56:02.647 回答