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