Given a 3+ way table, I'd like a simple, elegant way to flatten the table to a two-way table, with some variables joined interactively to form the rows and others forming the columns. For example, starting with > str(UCBAdmissions) table [1:2, 1:2, 1:6] 512 313 89 19 353 207 17 8 120 205 ... - attr(*, "dimnames")=List of 3 ..$ Admit : chr [1:2] "Admitted" "Rejected" ..$ Gender: chr [1:2] "Male" "Female" ..$ Dept : chr [1:6] "A" "B" "C" "D" ... > What I want is something similar to the result of ftable: > ftable(UCBAdmissions) Dept A B C D E F Admit Gender Admitted Male 512 353 120 138 53 22 Female 89 17 202 131 94 24 Rejected Male 313 207 205 279 138 351 Female 19 8 391 244 299 317 One way to do this is to convert to a data.frame, paste the factors together and then convert back to a table: UCB.df <- as.data.frame(UCBAdmissions) UCB.df$`Admit:Gender` <- paste(UCB.df$Admit, UCB.df$Gender, sep=':') UCB.tab2 <- xtabs(Freq ~ `Admit:Gender` + Dept, data=UCB.df) UCB.tab2 > UCB.tab2 Dept Admit:Gender A B C D E F Admitted:Female 89 17 202 131 94 24 Admitted:Male 512 353 120 138 53 22 Rejected:Female 19 8 391 244 299 317 Rejected:Male 313 207 205 279 138 351 > But maybe there is a simpler, more elegant and general way to do this. -- Michael Friendly Email: friendly AT yorku DOT ca Professor, Psychology Dept. & Chair, Quantitative Methods York University Voice: 416 736-2100 x66249 Fax: 416 736-5814 4700 Keele Street Web:http://www.datavis.ca Toronto, ONT M3J 1P3 CANADA
Do you just want to change how the rows and columns of ftable's output are labelled? If so, the following may do what you want: it produces a matrix with dimnames based on the row.vars and col.vars attributes of ftable's output. f <- function(ftable) { makeDimNamesEl <- function(x) { structure( list(do.call(paste, c(rev(expand.grid(rev(x))), list(sep=":")))), names = paste(collapse=":", names(x)) ) } structure( unclass(ftable), dimnames=c(makeDimNamesEl(attr(ftable, "row.vars")), makeDimNamesEl(attr(ftable, "col.vars"))), row.vars=NULL, col.vars=NULL) } E.g.,> f(ftable(UCBAdmissions))Dept Admit:Gender A B C D E F Admitted:Male 512 353 120 138 53 22 Admitted:Female 89 17 202 131 94 24 Rejected:Male 313 207 205 279 138 351 Rejected:Female 19 8 391 244 299 317> f(ftable(data=mtcars, am + gear ~ vs + carb))am:gear vs:carb 0:3 0:4 0:5 1:3 1:4 1:5 0:1 0 0 0 0 0 0 0:2 4 0 0 0 0 1 0:3 3 0 0 0 0 0 0:4 5 0 0 0 2 1 0:6 0 0 0 0 0 1 0:8 0 0 0 0 0 1 1:1 3 0 0 0 4 0 1:2 0 2 0 0 2 1 1:3 0 0 0 0 0 0 1:4 0 2 0 0 0 0 1:6 0 0 0 0 0 0 1:8 0 0 0 0 0 0 Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com> -----Original Message----- > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf > Of Michael Friendly > Sent: Thursday, January 09, 2014 7:14 AM > To: R-help > Subject: [R] recoding table dimensions interactively > > Given a 3+ way table, I'd like a simple, elegant way to flatten the > table to a two-way > table, with some variables joined interactively to form the rows and > others forming > the columns. For example, starting with > > > str(UCBAdmissions) > table [1:2, 1:2, 1:6] 512 313 89 19 353 207 17 8 120 205 ... > - attr(*, "dimnames")=List of 3 > ..$ Admit : chr [1:2] "Admitted" "Rejected" > ..$ Gender: chr [1:2] "Male" "Female" > ..$ Dept : chr [1:6] "A" "B" "C" "D" ... > > > > What I want is something similar to the result of ftable: > > > ftable(UCBAdmissions) > Dept A B C D E F > Admit Gender > Admitted Male 512 353 120 138 53 22 > Female 89 17 202 131 94 24 > Rejected Male 313 207 205 279 138 351 > Female 19 8 391 244 299 317 > > One way to do this is to convert to a data.frame, paste the factors > together and then convert back to a table: > > UCB.df <- as.data.frame(UCBAdmissions) > UCB.df$`Admit:Gender` <- paste(UCB.df$Admit, UCB.df$Gender, sep=':') > UCB.tab2 <- xtabs(Freq ~ `Admit:Gender` + Dept, data=UCB.df) > UCB.tab2 > > > UCB.tab2 > Dept > Admit:Gender A B C D E F > Admitted:Female 89 17 202 131 94 24 > Admitted:Male 512 353 120 138 53 22 > Rejected:Female 19 8 391 244 299 317 > Rejected:Male 313 207 205 279 138 351 > > > > But maybe there is a simpler, more elegant and general way to do this. > > -- > Michael Friendly Email: friendly AT yorku DOT ca > Professor, Psychology Dept. & Chair, Quantitative Methods > York University Voice: 416 736-2100 x66249 Fax: 416 736-5814 > 4700 Keele Street Web:http://www.datavis.ca > Toronto, ONT M3J 1P3 CANADA > > ______________________________________________ > 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.
Hi Michael, It's pretty easy with reshape: library(reshape2) ucbm <- melt(UCBAdmissions) acast(ucbm, Admit + Gender ~ Dept) acast(ucbm, Admit ~ Dept + Gender) acast(ucbm, Admit + Dept + Gender ~ .) # You can also do aggregations acast(ucbm, Admit ~ Dept, fun = sum) Hadley On Thu, Jan 9, 2014 at 9:14 AM, Michael Friendly <friendly at yorku.ca> wrote:> Given a 3+ way table, I'd like a simple, elegant way to flatten the table to > a two-way > table, with some variables joined interactively to form the rows and others > forming > the columns. For example, starting with > >> str(UCBAdmissions) > table [1:2, 1:2, 1:6] 512 313 89 19 353 207 17 8 120 205 ... > - attr(*, "dimnames")=List of 3 > ..$ Admit : chr [1:2] "Admitted" "Rejected" > ..$ Gender: chr [1:2] "Male" "Female" > ..$ Dept : chr [1:6] "A" "B" "C" "D" ... >> > > What I want is something similar to the result of ftable: > >> ftable(UCBAdmissions) > Dept A B C D E F > Admit Gender > Admitted Male 512 353 120 138 53 22 > Female 89 17 202 131 94 24 > Rejected Male 313 207 205 279 138 351 > Female 19 8 391 244 299 317 > > One way to do this is to convert to a data.frame, paste the factors together > and then convert back to a table: > > UCB.df <- as.data.frame(UCBAdmissions) > UCB.df$`Admit:Gender` <- paste(UCB.df$Admit, UCB.df$Gender, sep=':') > UCB.tab2 <- xtabs(Freq ~ `Admit:Gender` + Dept, data=UCB.df) > UCB.tab2 > >> UCB.tab2 > Dept > Admit:Gender A B C D E F > Admitted:Female 89 17 202 131 94 24 > Admitted:Male 512 353 120 138 53 22 > Rejected:Female 19 8 391 244 299 317 > Rejected:Male 313 207 205 279 138 351 >> > > But maybe there is a simpler, more elegant and general way to do this. > > -- > Michael Friendly Email: friendly AT yorku DOT ca > Professor, Psychology Dept. & Chair, Quantitative Methods > York University Voice: 416 736-2100 x66249 Fax: 416 736-5814 > 4700 Keele Street Web:http://www.datavis.ca > Toronto, ONT M3J 1P3 CANADA > > ______________________________________________ > 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.-- http://had.co.nz/