Select along one of n dimensions in array

后端 未结 4 1313
青春惊慌失措
青春惊慌失措 2020-12-05 19:53

I have an array in R, created by a function like this:

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

And I

相关标签:
4条回答
  • 2020-12-05 20:18

    I spent quite a lot of time figuring out the fastest way to do this for plyr, and the best I could come up with was manually constructing the call to [:

    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)
    }
    

    (You can find more information about this technique at https://github.com/hadley/devtools/wiki/Computing-on-the-language)

    You can then use it as follows:

    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)
    

    It would also generalise in a straightforward way if you want to extract based on more than one dimension, but you'd need to rethink the arguments to the function.

    0 讨论(0)
  • 2020-12-05 20:19

    I wrote this general function. Not necessarily super fast but a nice application for arrayInd and matrix indexing:

    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])
    
    }
    

    Example:

    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")
    
    0 讨论(0)
  • 2020-12-05 20:20

    Perhaps there is an easier way, but this works:

    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
    

    Let's generalize it into a function that can extract from any dimension, not necessarily the first one:

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

    Example:

    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")
    
    0 讨论(0)
  • 2020-12-05 20:31

    The abind package has a function, asub, to do this in addition to other very useful array manipulation functions:

    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)
    

    And it allows indexing in multiple dimensions:

    asub(A, list('x', c('C', 'D')), c(1,2))
    
    0 讨论(0)
提交回复
热议问题