[S] "list" format for table(): with order.list()

Don MacQueen (macqueen1@llnl.gov)
Fri, 22 May 1998 09:45:17 -0800


This is a resend of my table.list() function, with the required function
order.list() included. I apologize for omitting it the first time. See two
examples of uses for order.list() at the end.

Thanks to Tom Santner and Shawn Boles for telling me about my omission, and
Bill Dunlap for responding to the "how to do it better" question.

-Don

Back when I was a heavy SAS user, I almost always used the /list option in
proc freq. Here, in case anyone finds it useful, is a function named
table.list() that takes the result of the table() function and rearranges
it like a frequency tablulation using the /list option in SAS.

> args(table.list)
function(tbl, colnames = c(paste("arg", (1:ndim), sep = "."), "value"),
zero.rm = T, reorder = T)

-Don

Examples first:

> a1 <- rep( c('a','b','c'),4)
> a2 <- rep(c('x','y'),6)
> a3 <- c(rep('z3',8),rep('m3',3),'z3')

> tbl <- table(a1,a2,a3)
> tbl

, , m3
x y
a 0 1
b 1 0
c 1 0

, , z3
x y
a 2 1
b 1 2
c 1 2

> table.list(tbl,zero.rm=F,reorder=F)
arg.1 arg.2 arg.3 value
1 a x m3 0
2 b x m3 1
3 c x m3 1
4 a y m3 1
5 b y m3 0
6 c y m3 0
7 a x z3 2
8 b x z3 1
9 c x z3 1
10 a y z3 1
11 b y z3 2
12 c y z3 2

> table.list(tbl,colnames=c('a1','a2','a3','n'))
a1 a2 a3 n
4 a x z3 2
3 a y m3 1
7 a y z3 1
1 b x m3 1
5 b x z3 1
8 b y z3 2
2 c x m3 1
6 c x z3 1
9 c y z3 2

table.list <- function(tbl,colnames=c( paste('arg',(1:ndim),sep='.'), 'value'),
zero.rm=T,reorder=T) {

dims <- dim(tbl)
ndim <- length(dim(tbl))
vals <- as.vector(tbl)
nvals <- length(vals)
dimns <- dimnames(tbl)

nm <- rep(dimns[[1]],length=nvals)
for (i in 2:ndim) {
nm.i <- rep(dimns[[i]],rep(prod(dims[1:(i-1)]),dims[i]))
nm.i <- rep(nm.i,length=nvals)
nm <- cbind(nm,nm.i)
}

if (zero.rm) drop <- vals==0
else drop <- rep(F,length(vals))

out <- data.frame(nm[!drop,],vals[!drop])
names(out) <- colnames

if (reorder) {
ord <- order.list( as.list(out[, 1:ndim]) )
out <- out[ord,]
}

out
}

# 6/6/97
# order.list()
# Version of the order() function that takes a list argument
# requires list elements to be vectors of the same length
#
# Suppose xy <- list(x=10:1, y=(1:10)[runif(10)] )
# Then
# order.list(xy)
# returns the same value as
# order(xy$x,xy$y)
#
# probably should coerce zl to list, and add more checks for valid argument

order.list <- function(zl, na.last = T) {
p <- length(zl)
if(p == 1)
return(sort.list(zl[[1]], na.last = na.last))
n <- numeric(p)
for(i in 1:p)
n[i] <- length(zl[[i]])
m <- max(n)
if(m == 0)
return(integer(0))
keys <- 1:m
for(i in p:1) {
x <- if(n[i] < m) rep(zl[[i]], length = m) else zl[[i]]
keys <- keys[sort.list(x[keys], na.last = na.last)]
}
keys
}

# examples
# to sort a data frame by its first three columns do this:
# ord <- order.list( as.list(df[,1:3]) )
# df[ord,]
> foo <- list(x=c(2,2,1,1), m=c(2,2,2,1), c=c(8,1,7,2) )
> bah <- as.data.frame(foo)
> bah
x m c
1 2 2 8
2 2 2 1
3 1 2 7
4 1 1 2
> bah[order.list(foo),]
x m c
4 1 1 2
3 1 2 7
2 2 2 1
1 2 2 8

# to sort elements of a list, for plotting
> xy <- list(x=rep(1:4,2),y=runif(8))
> plot(xy,type='b')
> zz <- lapply( xy , function(x,xy) x[order.list(xy)],xy)
> plot(zz,type='b')

--------------------------------
Don MacQueen
Environmental Protection Dept.
Lawrence Livermore National Lab
macq@llnl.gov (925) 423-1062
--------------------------------

-----------------------------------------------------------------------
This message was distributed by s-news@wubios.wustl.edu. To unsubscribe
send e-mail to s-news-request@wubios.wustl.edu with the BODY of the
message: unsubscribe s-news