[R] Subsetting an array by a vector of dimensions

Wolfgang Huber huber at ebi.ac.uk
Sat Jul 12 00:34:06 CEST 2008


Kenn Konstabel wrote:
> What is "wrong" is, I think, that you can't write a substitute for 
> x[1,2,] this way. (Or, in general, empty indexes won't work.)
> 
> A related question - Is there a way to replace x[1,2,] with "["(1,2, 
> *something clever*)  ?
> 
> Kenn


Dear Kenn,

I can:

 > do.call("[", list(x,1,2,TRUE))
[1]  3  9 15 21

See also http://134.148.236.121/R/help/06/01/19403.html


In principle this works also for assignment, but the following benchmark 
shows a big performance hit:

x = array(1:1e6, dim=c(100,100,100))

system.time({
   for(i in 1:100)  x = do.call("[<-", list(x, i, 2, TRUE, pi))
})

system.time({
   for(i in 1:100)  x[i, 2, ] <- pi
})

The first takes ~2sec on my computer, the second 8ms, and I wonder 
whether someone knows how to use the "clever" behaviour of "[<-" also 
when it is called with do.call?

  Best wishes
	Wolfgang


----------------------------------------------------
Wolfgang Huber, EMBL-EBI, http://www.ebi.ac.uk/huber


> 
> 
> On Sat, Jul 12, 2008 at 12:48 AM, Wolfgang Huber <huber a ebi.ac.uk 
> <mailto:huber a ebi.ac.uk>> wrote:
> 
> 
>     Hi Richard,
> 
>     what is wrong with Patrick's suggestion? I get
> 
> 
>     x <- array(1:24, dim=2:4)
>     x[rbind(c(1,1,2))]
>     ## [1] 7
>     x[rbind(c(1,1,2))] <- 13
>     x[rbind(c(1,1,2))]
>     ## [1] 13
> 
>     And you could also do
> 
>      do.call("[", list(x,1,1,2))
> 
>     These should be a bit quicker than the eval/parse constructs - see
>     also        
>            library("fortunes")
>            fortune(106)
> 
>     Also note that your "subsetArray<-" function will afaIu each time
>     copy (and then modify) the whole array, which may be quite
>     inefficient. I believe that the "[<-" function has been optimized to
>     avoid that in some cases. Try
> 
>      x=numeric(1e6); system.time({for (i in 1:1000) x[i]=12})
> 
>     versus
> 
>      x=numeric(1e6); system.time({for (i in 1:1000) {y=x; y[i]=12}})
> 
>            Best wishes
>            Wolfgang
> 
>     ----------------------------------------------------
>     Wolfgang Huber, EMBL-EBI, http://www.ebi.ac.uk/huber
> 
> 
> 
> 
> 
>     Richard Pearson wrote:
> 
>         In case anyone's still interested, I now have (I think!) a
>         complete solution (thanks to a quick look at my new favourite
>         document - S Poetry :-)
> 
>         subsetArray <- function(x, subset) {
>          subsetString <- paste(subset, collapse=",")
>          subsetString <- gsub("NA","",subsetString)
>          evalString <- paste(expression(x), "[", subsetString, "]")
>          eval(parse(text=evalString))
>         }
> 
>         "subsetArray<-"<- function(x, subset, value) {
>          subsetString <- paste(subset, collapse=",")
>          subsetString <- gsub("NA","",subsetString)
>          evalString <- paste(expression(x), "[", subsetString, "] <-",
>         expression(value))
>          eval(parse(text=evalString))
>          x
>         }
> 
>         x <- array(1:24, dim=2:4)
>         subsetArray(x, c(1,1,2))
>         subsetArray(x, c(1,1,2)) <- 25
>         x
> 
>         Thanks to Pat!
> 
>         Richard
> 
> 
>         Richard Pearson wrote:
> 
>             My understanding of matrix subscripting is that this can be
>             used to access arbitrary elements from an array and return
>             them as a vector, but I don't understand how that helps me
>             here. I've now written a function that seems to do what I
>             originally wanted, but I've also realised I want to do
>             assignment too. I need to read up more on writing assignment
>             functions to do this. However, I'm thinking that someone has
>             already solved this, in a far more elegant way than my
>             hacking :-). Here's my function for anyone interested:
> 
>                 subsetArray <- function(x, subset) {
> 
>             +   subsetString <- paste(subset, collapse=",")
>             +   subsetString <- gsub("NA","",subsetString)
>             +   evalString <- paste(expression(x), "[", subsetString, "]")
>             +   eval(parse(text=evalString))
>             + }
> 
>                 x <- array(1:24, dim=2:4)
>                 subsetArray(x, c(1,1,2))
> 
>             [1] 7
> 
>                 subsetArray(x, c(1,NA,2))
> 
>             [1]  7  9 11
> 
>                 subsetArray(x, c(1,NA,NA))
> 
>                [,1] [,2] [,3] [,4]
>             [1,]    1    7   13   19
>             [2,]    3    9   15   21
>             [3,]    5   11   17   23
> 
> 
>                 subsetArray(x, c(1,1,2)) <- 25
> 
>             Error in subsetArray(x, c(1, 1, 2)) <- 25 :  could not find
>             function "subsetArray<-"
> 
>             Best wishes
> 
>             Richard.
> 
> 
>             Patrick Burns wrote:
> 
>                 I think you are looking for subscripting with a
>                 matrix:
> 
>                 x[cbind(1,1,2)]
> 
>                 See, for instance, the subscripting section of chapter 1
>                 of S Poetry.
> 
> 
>                 Patrick Burns
>                 patrick a burns-stat.com <mailto:patrick a burns-stat.com>
>                 +44 (0)20 8525 0696
>                 http://www.burns-stat.com
>                 (home of S Poetry and "A Guide for the Unwilling S User")
> 
>                 Richard Pearson wrote:
> 
>                     Hi
> 
>                     Is it possible to subset an n-dimensional array by a
>                     vector of n dimensions? E.g. assume I have
> 
>                         x <- array(1:24, dim=2:4)
>                         x[1,1,2]
> 
>                     [1] 7
> 
>                         dims <- c(1,1,2)
> 
> 
>                     I would like a function that I can supply x and dims
>                     as parameters to, and have it return 7. Also, I
>                     would like to do something like:
> 
>                         x[1,1,]
> 
>                     [1]  1  7 13 19
> 
>                         dims2<- c(1,1,NA)
> 
> 
>                     And have a function of x and dims2 that gives me
>                     back [1]  1  7 13 19
> 
>                     Does such a thing exist?
> 
>                     Thanks
> 
>                     Richard
> 
> 
>     ______________________________________________
>     R-help a r-project.org <mailto:R-help a r-project.org> mailing list
>     https://stat.ethz.ch/mailman/listinfo/r-help
>     PLEASE do read the posting guide
>     http://www.R-project.org/posting-guide.html
>     and provide commented, minimal, self-contained, reproducible code.
> 
>



More information about the R-help mailing list