Thaler, Thorn, LAUSANNE, Applied Mathematics
2010-Jul-20 09:29 UTC
[R] apply: return list of matrices
Hi everybody, Suppose we have the following data structure: ddf <-data.frame(a=rep(1:4,3), b=rep(paste("p", 1:3, sep=""), each=4), c=c(1,0,0,1,1,1,0,1,1,1,1,1)) I want now to make a contingency table for each pair of values of p, i.e. a contingency table for each of the pairs (p1,p2), (p1,p3) and (p2,p3). The result should be given as a list of matrices: # [[1]] <=> (p1, p2) # [[2]] <=> (p1, p3) # [[3]] <=> (p2, p3) [[1]] [,1] [,2] [1,] 1 1 [2,] 0 2 [[2]] [,1] [,2] [1,] 0 2 [2,] 0 2 [[3]] [,1] [,2] [1,] 0 1 [2,] 0 3 Basically, I achieved what I want except that the output format is not the way it should be: ct <- function(bc) { n <- length(bc) bc <- factor(bc) table(bc[1:(n/2)], bc[(n/2+1):n]) } ct returns a 2x2 table giving the contingency counts. f <- function(p, b) { allC <- t(combn(levels(as.factor(p)), 2)) bRaw <- apply(allC, 1, function(x) cbind(b[p==x[1]], b[p==x[2]])) # bRaw would preferable be already a list of nx2 matrices, but apply coerces the result to a single matrix, # whose columns are rbind(b[p==x[1]], b[p==x[2]]), that's why "ct" takes just one argument and splits the vector apply(bRaw, 2, ct) } Again the result is one single matrix instead of list of matrices (the columns consist of the values of the matrices). I suppose that apply does some sophisticated simplification on the result vector, but how can I circumvent this mechanism? For the time being I made another *apply call, which gives me the same result in the format I'd like: just replace the last line in function f by lapply(apply(bRaw, 2, function(x) list(ct(x))), function(x) matrix(unlist(x),2,2)) However, is an additional lapply call really necessary? Thanks 4 ur input, Thorn
one approach is the following: ddf <- data.frame(a = rep(1:4,3), b = rep(paste("p", 1:3, sep=""), each=4), c = c(1,0,0,1,1,1,0,1,1,1,1,1)) sp <- lapply(split(ddf$c, ddf$b), factor, levels = 0:1) combn(sp, 2, FUN = table, simplify = FALSE) I hope it helps. Best, Dimitris On 7/20/2010 11:29 AM, Thaler, Thorn, LAUSANNE, Applied Mathematics wrote:> Hi everybody, > > Suppose we have the following data structure: > > ddf<-data.frame(a=rep(1:4,3), b=rep(paste("p", 1:3, sep=""), each=4), > c=c(1,0,0,1,1,1,0,1,1,1,1,1)) > > I want now to make a contingency table for each pair of values of p, > i.e. a contingency table for each of the pairs (p1,p2), (p1,p3) and > (p2,p3). The result should be given as a list of matrices: > > # [[1]]<=> (p1, p2) > # [[2]]<=> (p1, p3) > # [[3]]<=> (p2, p3) > [[1]] > [,1] [,2] > [1,] 1 1 > [2,] 0 2 > > [[2]] > [,1] [,2] > [1,] 0 2 > [2,] 0 2 > > [[3]] > [,1] [,2] > [1,] 0 1 > [2,] 0 3 > > Basically, I achieved what I want except that the output format is not > the way it should be: > > ct<- function(bc) { > n<- length(bc) > bc<- factor(bc) > table(bc[1:(n/2)], bc[(n/2+1):n]) > } > > ct returns a 2x2 table giving the contingency counts. > > f<- function(p, b) { > allC<- t(combn(levels(as.factor(p)), 2)) > bRaw<- apply(allC, 1, function(x) cbind(b[p==x[1]], b[p==x[2]])) > > # bRaw would preferable be already a list of nx2 matrices, but apply > coerces the result to a single matrix, > # whose columns are rbind(b[p==x[1]], b[p==x[2]]), that's why "ct" > takes just one argument and splits the vector > > apply(bRaw, 2, ct) > } > > Again the result is one single matrix instead of list of matrices (the > columns consist of the values of the matrices). I suppose that apply > does some sophisticated simplification on the result vector, but how can > I circumvent this mechanism? For the time being I made another *apply > call, which gives me the same result in the format I'd like: just > replace the last line in function f by > > lapply(apply(bRaw, 2, function(x) list(ct(x))), function(x) > matrix(unlist(x),2,2)) > > However, is an additional lapply call really necessary? > > Thanks 4 ur input, > > Thorn > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >-- Dimitris Rizopoulos Assistant Professor Department of Biostatistics Erasmus University Medical Center Address: PO Box 2040, 3000 CA Rotterdam, the Netherlands Tel: +31/(0)10/7043478 Fax: +31/(0)10/7043014