Search code examples
rarraysindexing

Dynamically access array dimension


is there a way to dynamically access an array dimension (ideally without reshaping)? I have an n-dimensional array arr as well as a named order of dimensions vals. Both the number of dimensions for arr and the order of vals may change. I always want to access the first entry of arr for the dimension where vals equals B. In the following I have provided three examples demonstrating what I want:

#Example 1
vals = c("A","B","C")
idx = grep("B",vals)
arr = array(runif(5^3), dim = c(5,5,5))

arr[,1,] # B is in second dimension

#Example 2
vals = c("A","C","B","D")
idx = grep("B",vals)
arr = array(runif(5^4), dim = c(5,5,5,5))

arr[,,1,] #B is in third dimension

#Example 3
vals = c("B","A","C","D","E")
idx = grep("B",vals)
arr = array(runif(5^5), dim = c(5,5,5,5,5))

arr[1,,,,] #B is in first dimension

I'm absolutely clueless how to approach this.


Solution

  • I think the simplest way is using asplit (but seems not as efficient as eval approach)

    asplit(arr, idx)[[1]]
    

    Other options


    You can also try apply like below

    array(apply(arr, idx, c)[, 1], dim(arr)[-idx])
    

    and verify it, for example

    > set.seed(0)
    
    > vals <- c("B", "A", "C", "D", "E")
    
    > idx <- grep("B", vals)
    
    > arr <- array(runif(5^5), dim = c(5, 5, 5, 5, 5))
    
    > a <- arr[1, , , , ] # B is in first dimension
    
    > b <- array(apply(arr, idx, c)[, 1], dim(arr)[-idx])
    
    > all.equal(a, b)
    [1] TRUE
    

    If you are bothered by apply and its indexing logic, you can parse the string like

    b <- eval(str2lang(sprintf("arr[%s]", toString(replace(rep("", length(dim(arr))), idx, "1")))))
    

    and you can obtain

    > all.equal(a, b)
    [1] TRUE