Hi, I recently encountered a problem with array subsetting and came up with a fix. Given an array of arbitrary dimensions, in which the number of dimensions is only known at runtime, I wanted to extract a subarray. The main issue with doing this is that in order to extract a subarray from an array of (say) 4 dimensions you usually specify something like this
a.subarray <- a[,c(4,2),1:5,] However, if your code needs to handle an array with an arbitrary number of dimensions then you can't hard code the number of commas while writing the code. (Regarding motivation, the reason this came up is because I wanted to do some toy problems involving conditioning on multiple variables in a multidimensional joint pmf.) I looked through commands like slice.index and so on, but they seemed to require reshaping and big logical matrix intermediates, which were not memory efficient enough for me. apltake in the magic package was the closest but it only allowed subsetting of contiguous indices from either the first or last element in any given dimension. It was certainly possible to call apltake multiple times to extract arbitrary subarrays via combinations of index intervals for each dimension, and then combine them with abind as necessary, but this did not seem elegant. Anyway, I then decided to simply generate code with parse and eval. I found this post by Henrik Bengtsson which had the same idea: http://tolstoy.newcastle.edu.au/R/devel/05/11/3266.html I just took that code one step further and put together a utility function that I think might be fairly useful. I haven't completely robustified it against all kinds of pathological inputs, but if there is any interest from the development team it would be nice to add an error-checked version of this to R (or I guess I could keep it in a package). Simple usage example: ------ > source("arraytake.R") > a <- array(1:24,c(2,3,4)) > a[,1:3,c(4,2)] ##This invocation requires hard coding the number of dimensions of a , , 1 [,1] [,2] [,3] [1,] 19 21 23 [2,] 20 22 24 , , 2 [,1] [,2] [,3] [1,] 7 9 11 [2,] 8 10 12 > arraytake(a,list(NULL,1:3,c(4,2))) ##This invocation does not, and produces the same result , , 1 [,1] [,2] [,3] [1,] 19 21 23 [2,] 20 22 24 , , 2 [,1] [,2] [,3] [1,] 7 9 11 [2,] 8 10 12 Code below: -------- arraytake <- function(x,indlist) { #Returns subarrays of arbitrary dimensioned arrays #1) Let x be a multidimensional array with an arbitrary number of dimensions. #2) Let indlist be a list of vectors. The length of indlist is the same as the number of #dimensions in x. Each element of the indlist is a vector which specifies which #indexes to extract in the corresponding dimension. If the element of the indlist is #NULL, then we return all elements in that dimension. #The main way this works is by programmatically building up a comma separated argument to "[" as a string #and then simply evaluating that expression. This way one does not need to specify the number of #commas. if(length(dim(x)) != length(indlist)) { return(); #we would put some error message here in production code } #First build up a string w/ indices for each dimension d <- length(indlist); #number of dims indvecstr <- matrix(0,d,1); for(i in 1:d) { if(is.null(indlist[[i]])) { indvecstr[i] <- ""; } else{ indvecstr[i] <- paste("c(",paste(indlist[[i]],sep="",collapse=","),")",sep="") } } #Then build up the argument string to "[" argstr <- paste(indvecstr,sep="",collapse=",") argstr <- paste("x[",argstr,"]",sep="") #Finally, return the subsetted array return(eval(parse(text=argstr))) } -- Dr. Balaji S. Srinivasan Stanford University Depts. of Statistics and Computer Science 318 Campus Drive, Clark Center S251 (650) 380-0695 [EMAIL PROTECTED] http://jinome.stanford.edu [[alternative HTML version deleted]] ______________________________________________ [email protected] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
