[Rd] a patch to tapply (PR#1186)

vograno@arbitrade.com vograno@arbitrade.com
Thu, 29 Nov 2001 21:48:57 +0100 (MET)


Though tapply(x, factor, fun, simplify =TRUE) should be equivalent to
sapply(split(x, factor), fun, simplify=TRUE), note simplify=TRUE, it is not
so if fun() returns a vector rather than a scalar, e.g.

> tapply(1:6, c(0,0,0,1,1,1), function(x) c(min=min(x), max=max(x)),
simplify=TRUE)
$"0"
min max 
  1   3 

$"1"
min max 
  4   6 

> sapply(split(1:6, c(0,0,0,1,1,1)), function(x) c(min=min(x), max=max(x)),
simplify=TRUE)
    0 1
min 1 4
max 3 6

The patch submitted below fixes this problem
> tapply.new(1:6, c(0,0,0,1,1,1), function(x) c(min=min(x), max=max(x)),
simplify=TRUE)
    0 1
min 1 4
max 3 6

Another potential problem, which I am not able to verify at the moment, is
that whenever simplification is possible S-Plus returns a TRANSPOSE of that
of R, i.e.
  min max
0   1   3
1   4   6

Fixing this would require small changes to both tapply and sapply and I'll
be happy to provide the patches if requested.


R Version
> sapply(R.Version(), I)
           platform                arch                  os
system 
"i686-pc-linux-gnu"              "i686"         "linux-gnu"   "i686,
linux-gnu" 
             status               major               minor
year 
                 ""                 "1"               "3.1"
"2001" 
              month                 day            language 
               "08"                "31"                 "R"

 **************
The patch:
"tapply.new" <-
  function (X, INDEX, FUN = NULL, ..., simplify = TRUE) 
{
  FUN <- if (!is.null(FUN)) 
    match.fun(FUN)
  if (!is.list(INDEX)) 
    INDEX <- list(INDEX)
  nI <- length(INDEX)
  namelist <- vector("list", nI)
  names(namelist) <- names(INDEX)
  extent <- integer(nI)
  nx <- length(X)
  one <- as.integer(1)
  group <- rep(one, nx)
  ngroup <- one
  for (i in seq(INDEX)) {
    index <- as.factor(INDEX[[i]])
    if (length(index) != nx) 
      stop("arguments must have same length")
    namelist[[i]] <- levels(index)
    extent[i] <- nlevels(index)
    group <- group + ngroup * (as.integer(index) - one)
    ngroup <- ngroup * nlevels(index)
  }
  if (is.null(FUN)) 
    return(group)
  ans <- lapply(split(X, group), FUN, ...)
  if (simplify && length(common.len <- unique(unlist(lapply(ans, length))))
== 1) {
    if (common.len > 1) {
      extent <- c(common.len, extent)
      namelist <- c(list(names(ans[[1]])), namelist)
    }
    ansmat <- array(unlist(ans, recursive = FALSE), dim = extent, dimnames =
namelist)
    return(ansmat)
  }
  index <- as.numeric(names(ans))
  ansmat <- array(vector("list", prod(extent)), dim = extent, 
                  dimnames = namelist)
  names(ans) <- NULL
  ansmat[index] <- ans
  ansmat
}

-------------------------------------------------- 
DISCLAIMER 
This e-mail, and any attachments thereto, is intended only for use by the
addressee(s) named herein and may contain legally privileged and/or
confidential information.  If you are not the intended recipient of this
e-mail, you are hereby notified that any dissemination, distribution or
copying of this e-mail, and any attachments thereto, is strictly prohibited.
If you have received this e-mail in error, please immediately notify me and
permanently delete the original and any copy of any e-mail and any printout
thereof. 

E-mail transmission cannot be guaranteed to be secure or error-free.  The
sender therefore does not accept liability for any errors or omissions in
the contents of this message which arise as a result of e-mail transmission.

NOTICE REGARDING PRIVACY AND CONFIDENTIALITY 

Knight Trading Group may, at its discretion, monitor and review the content
of all e-mail communications. 


-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._