[R] Subarray specification problem

Roy Shimizu rshmz29 at gmail.com
Sat Dec 18 14:54:16 CET 2010


On Fri, Dec 17, 2010 at 8:58 AM, Michael Friendly <friendly at yorku.ca> wrote:
> Use aperm() to make time the first dimension
> Reshape to a matrix (all other dimensions combined)
> Do your selection on X[1,]
> aperm() to Permute back

To Michael, thanks!

I copy my implementation of Michael's idea at the end of this post.

My implementation is long and labored, at least when compared to
Michael's succinct description of its strategy.

How much this is due to my inexperience with R, and how much is due to
R's intrinsic limitations for this kind of problem?  Could this be
done substantially more succinctly by a more expert programmer?  In
particular, are there some features of R that I'm not using in my
implementation, and that would greatly simplify it?

Also, I wonder about the scalability of such a solution, since it
requires the wholesale reshaping of the array, which doubles the
memory requirement, and maybe would be costly in time as well.

I generalized my implementation to a function called select.subarray,
that takes three arguments: an array, the name of some dimension in
the array, and an predicate to apply to the dimnames in this
dimension; it returns the subarray of the original array in which all
the dimnames in the named dimension satisfy the predicate.

When applied to my original problem, it seems to work.  First a recap of x:

> x
, , 1

      time
              84        69        61         16        77
  [1,] 0.4020976 0.8250189 0.3402749 0.09754860 0.2189114
  [2,] 0.5309967 0.5414850 0.9431449 0.08716723 0.5819100

, , 2

      time
              84        69        61        16        77
  [1,] 0.6238213 0.1210083 0.7823269 0.5004058 0.5474356
  [2,] 0.2491087 0.7449411 0.9561074 0.6685954 0.3871533


And now, applying select.subarray to solve my original problem:

> select.subarray(x, "time", function(x) { i <- as.integer(x); 20 < i & i < 80 })
, , 1

      time
              69        61        77
  [1,] 0.8250189 0.3402749 0.2189114
  [2,] 0.5414850 0.9431449 0.5819100

, , 2

      time
              69        61        77
  [1,] 0.1210083 0.7823269 0.5474356
  [2,] 0.7449411 0.9561074 0.3871533



OK, here's the beast.  It does no error checking, both for the sake of
simplicity, and because I really don't know enough R yet to handle
errors intelligently.

select.subarray <- function(an.array, dim.name, predicate) {
    dim.index <- which(names(dimnames(an.array)) == dim.name)
    reordering.perm <- c(dim.index, seq(along=dim(an.array))[-dim.index])

    permuted.array <- aperm(an.array, reordering.perm)

    # save the dim and dimnames of permuted.array for reuse later
    d.permuted.array <- dim(permuted.array)
    dn.permuted.array <- dimnames(permuted.array)

    dim.dimnames <- as.integer(dn.permuted.array[[1]])
    permuted.array.matrix <-
      	array(permuted.array,
      	      dim=c(d.permuted.array[1], sum(d.permuted.array[-1])),
      	      dimnames=list(dim.dimnames, NULL))

    indices.to.keep <- which(predicate(dim.dimnames))

    new.dimnames.permuted <- c(list(dim.dimnames[indices.to.keep]),
                               dn.permuted.array[-1])
    names(new.dimnames.permuted)[1] <- dim.name

    desired.subarray.permuted <-
      	array(permuted.array.matrix[indices.to.keep,],
      	      dim=c(length(indices.to.keep), d.permuted.array[-1]),
      	      dimnames=new.dimnames.permuted)

    # the desired subarray
    aperm(desired.subarray.permuted, order(reordering.perm))
}


As I said, I'm very new to R, and would more than welcome any
comments/suggestions/constructive criticism on this code.


Roy



More information about the R-help mailing list