Reputation: 337
I have following array (in an example 3-dimensional, but it can be 3+ dims):
a <- c('a1', 'a2', 'a3')
b <- c('bb', 'bbb')
c <- c('C', 'CC', 'CCC')
dimNa <- list('a' = a, 'b' = b, 'c' = c)
outputArray <- array(NA,
unname(sapply(dimNa, function(x) length(x), simplify = T)),
unname(dimNa))
I can subset it using name from one dimension manually, like:
> outputArray[,'bb',]
C CC CCC
a1 NA NA NA
a2 NA NA NA
a3 NA NA NA
or
> outputArray[,,'CCC']
bb bbb
a1 NA NA
a2 NA NA
a3 NA NA
The question is how to pass a vector (or sth else? - in this case ,'bb',
and ,,'CCC'
) to [
, so I can write a function to generate this automatically (assuming that I can extract info regarding which name is stored in which dimension - names are unique and I can get this info from dimnames(outputArray)
)? Just like I mentioned array can be 3+ dims.
Edit: I would like to subset by name only from one dimension. So outputArray[,'bb',]
or outputArray[,,'CCC']
, not outputArray[,'bb','CCC']
, but solution should work for more dimensions.
Upvotes: 0
Views: 219
Reputation: 337
Thanks to How to pass/use string in [ to subset I was able to create following function (using abind::asub
):
library("abind")
subsetElement <- function(inputArray, whichIdx){
whichDim <- NULL
dimNames <- dimnames(inputArray)
for (dn in seq_len(length(dimNames))){
if (whichIdx %in% dimNames[[dn]]){
whichDim <- dn
break
}
}
if(!is.null(whichDim)){
return(abind::asub(inputArray, whichIdx, whichDim))
}
return(NULL)
}
It works only if indices are unique.
> subsetElement(outputArray, 'bb')
C CC CCC
a1 NA NA NA
a2 NA NA NA
a3 NA NA NA
> subsetElement(outputArray, 'C')
bb bbb
a1 NA NA
a2 NA NA
a3 NA NA
Upvotes: 1
Reputation: 887078
We can create the three dimensional index and use Map
to extract for each of the cases
d1 <- dim(outputArray)
Map(function(i,j,k) outputArray[i,j,k],
list(seq_len(d1[1])), list('bb', seq_len(d1[2])), list(seq_len(d1[3]), 'CCC'))
#[[1]]
# C CC CCC
#a1 NA NA NA
#a2 NA NA NA
#a3 NA NA NA
#[[2]]
# bb bbb
#a1 NA NA
#a2 NA NA
#a3 NA NA
Upvotes: 0