From r.hankin at noc.soton.ac.uk  Thu Oct 19 15:24:24 2006
From: r.hankin at noc.soton.ac.uk (Robin Hankin)
Date: Thu, 19 Oct 2006 14:24:24 +0100
Subject: [Rd] arraytake for extracting subarrays from multidimensional
	arrays
In-Reply-To: <39422c340610190605v266f31eet28252a4f09b0dabe@mail.gmail.com>
References: <39422c340610190605v266f31eet28252a4f09b0dabe@mail.gmail.com>
Message-ID: <8E95D83B-82A1-4754-AB91-1DA1431E29DF@soc.soton.ac.uk>

Hi

Your arraytake() function does indeed do something
that can't be done elegantly by apltake(), AFAICS

I think that arraytake() would make a splendid addition
to the magic package.

Would that be acceptable?

best wishes


rksh


[I can't help thinking that a judicious use of do.call() could
replace the eval(parse(text=...)) construction tho' . . .]





does more-or-less this.

On 19 Oct 2006, at 14:05, Balaji S. Srinivasan wrote:

> 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
> balajis at stanford.edu
> http://jinome.stanford.edu
>
> 	[[alternative HTML version deleted]]
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

--
Robin Hankin
Uncertainty Analyst
National Oceanography Centre, Southampton
European Way, Southampton SO14 3ZH, UK
  tel  023-8059-7743




[Rd] arraytake for extracting subarrays from multidimensional arrays
Robin Hankin