Skip to content
Prev 38759 / 63424 Next

aperm() should retain class of input object

On 12/28/2010 9:43 AM, Tim Hesterberg wrote:
OK.  I can see that my initial proposal would be dangerous for xtabs 
objects without further
modifications and that it is unwise to change default behavior in base 
functions without
very strong reasons.
This first option is the minimally invasive corrective surgery.
This would put the burden on the user (or package writer), but at least 
make it known
that keep.class=TRUE is an option.  This version is

## add keep.class, non-generic
aperm <- function (a, perm, resize = TRUE, keep.class=FALSE)
{
     if (missing(perm))
         perm <- integer(0L)
     result <- .Internal(aperm(a, perm, resize))
     if(keep.class) class(result) <- class(a)
     result
}
This would be much better, as long as an aperm.table method was added to 
base, to complement table() itself,
and gives the desired behavior for table objects by default.
This version seems to be:

## make generic, with ...
aperm <- function(a, ...)
     UseMethod("aperm", ...)

aperm.default <- function (a, perm, resize = TRUE, ...)
{
     if (missing(perm))
         perm <- integer(0L)
     .Internal(aperm(a, perm, resize))
}

aperm.table <- function(a, perm, resize=TRUE, keep.class=TRUE, ...)
{
     result <- aperm.default(a, perm, resize=resize)
     if(keep.class) class(result) <- class(a)
     result
}

But it throws an error, maybe because I haven't redefined aperm as a 
generic:

 > UCB <- aperm(UCBAdmissions, c(2,1,3))
Error in aperm(UCBAdmissions, c(2, 1, 3)) :
   '...' used in an incorrect context

The .table method does work as desired:

 > UCB <- aperm.table(UCBAdmissions, c(2,1,3))
 > str(UCB)
  table [1:2, 1:2, 1:6] 512 89 313 19 353 17 207 8 120 202 ...
  - attr(*, "dimnames")=List of 3
   ..$ Gender: chr [1:2] "Male" "Female"
   ..$ Admit : chr [1:2] "Admitted" "Rejected"
   ..$ Dept  : chr [1:6] "A" "B" "C" "D" ...
 >