From tplate at acm.org  Thu Nov 24 03:33:46 2005
From: tplate at acm.org (Tony Plate)
Date: Wed, 23 Nov 2005 19:33:46 -0700
Subject: [Rd] x[1,], x[1,,], x[1,,,], ...
In-Reply-To: <43850A5F.5090508@maths.lth.se>
References: <4384498B.1080401@maths.lth.se> <x2oe4br07p.fsf@viggo.kubism.ku.dk>
	<43850A5F.5090508@maths.lth.se>
Message-ID: <4385268A.7080308@acm.org>

Henrik Bengtsson wrote:
> Hi, thanks everyone.
> 
> Some comments below:
> 
> Peter Dalgaard wrote:
> 
>>Henrik Bengtsson <hb at maths.lth.se> writes:
>>
>>
>>
>>>Hi,
>>>
>>>is there a function in R already doing what I try to do below:
>>>
>>># Let 'x' be an array with *any* number of dimensions (>=1).
>>>x <- array(1:24, dim=c(2,2,3,2))
>>>...
>>>x <- array(1:24, dim=c(4,3,2))
>>>
>>>i <- 2:3
>>>
>>>ndim <- length(dim(x))
>>>if (ndim == 1)
>>>  y <- x[i]
>>>else if (ndim == 2)
>>>  y <- x[i,]
>>>else if (ndim == 3)
>>>  y <- x[i,,]
>>>else ...
>>>
>>>and so on.  My current solution is
>>>
>>>ndim <- length(dim(x))
>>>args <- rep(",", ndim)
>>>args[1] <- "i"
>>>args <- paste(args, collapse="")
>>>code <- paste("x[", args, "]", sep="")
>>>expr <- parse(text=code)
>>>y <- eval(expr)
>>>
>>>Is there another way I can do this in R that I have overlooked?
>>
>>
>>I think this should work:
>>
>>x <- array(1:24, dim=c(3,2,2,2)) # not c(2,2,3,2)....
>>i <- 2:3
>>ndim <- length(dim(x))
>>ix <- as.list(rep(TRUE, ndim))
>>ix[[1]] <- i
>>do.call("[", c(list(x), ix))
> 
> 
> In my case, 'x' is huge, an I have to be careful with allocating memory. 
> Doesn't the 'list(x)' statement enforce an extra copy of 'x'?  Or will 
> lazy evaluation be able to pull out 'x' from the list again without 
> evaluating 'list(x)'?  I don't think so, but I'm not sure.  There is 
> also some overhead in 'ix[[1]] <- i', but 'i' is typically much smaller 
> than 'x' so this should be of minor importance.
> 
> What about Andy's suggestion
> 
>    array(x[slice.index(x, 1) == 1], dim(x)[-1])?
> 
> There 'slice.index(x, 1)' will create an array of same size as 'x'.
> 
> I do not think the 'eval(parse(...))' has such overhead (correct me if 
> I'm wrong), but on the other hand, it is a more "ugly" solution. I 
> prefer not to use parse(), substitute() and friends in my code, if I 
> don't have to.
> 
> I just want to bring up this flavor of the problem too, because I often 
> find myself having to choose from similar options in other situations. 
> If you have further comments, I would appreciate those.
> 

Here's the type of manipulation I often do to approach these problems:

 > x <- array(1:24, dim=c(4,3,2))
 > i <- 2:3
 > x[i,,]
, , 1

      [,1] [,2] [,3]
[1,]    2    6   10
[2,]    3    7   11

, , 2

      [,1] [,2] [,3]
[1,]   14   18   22
[2,]   15   19   23

 > xic <- Quote(x[i,])
 > xic
x[i, ]
 > length(xic)
[1] 4
 > # now duplicate the empty index argument the appropriate number of times
 > xic <- xic[c(1:3,4,4)]
 > xic
x[i, , ]
 > eval(xic)
, , 1

      [,1] [,2] [,3]
[1,]    2    6   10
[2,]    3    7   11

, , 2

      [,1] [,2] [,3]
[1,]   14   18   22
[2,]   15   19   23

 >

I do this type of manipulation for precisely the reasons you bring up. 
I do know that in S-PLUS, using do.call() in the most obvious manner can 
result in unnecessary multiple duplications of data objects (as you 
suspect).  I don't think R is quite as bad, but I haven't done careful 
the experiments with R.

Do be careful though: this type of manipulation can expose a bug in R, 
which I don't think has been fixed (PR#7924).

-- Tony Plate

> Thanks
> 
> Henrik
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] x[1,], x[1,,], x[1,,,], ...
Tony Plate