[R] recoding table dimensions interactively

Michael Friendly friendly at yorku.ca
Thu Jan 9 20:29:34 CET 2014


Thanks for this, Bill

Your solution does just what I want.  In fact, it qualifies as the 
missing as.matrix() method
for n-way tables arranged with ftable(), or vcd::structable(), which 
does provide an
as.matrix() method, but omits the names and dimnames.

Here it is, renamed and
using "_" as the default separator for names joined together, which is 
probably a better
default.  I'll propose this as an addition to the stats package on R-devel.


# modified from Willaim Dunlop, <wdunlap at tibco.com>, R-Help, 01-09-2014
as.matrix.ftable <- function(x, sep="_") {
     makeDimNames <- function(vars) {
         structure(
             list(do.call(paste, c(rev(expand.grid(rev(vars))), 
list(sep=sep)))),
             names = paste(collapse=sep, names(vars))
         )
     }
     structure(
         unclass(x),
         dimnames=c(makeDimNames(attr(x, "row.vars")),
                    makeDimNames(attr(x, "col.vars"))),
         row.vars=NULL,
         col.vars=NULL)
}

Tests:

 > UCB <- UCBAdmissions
 > as.matrix(ftable(Dept ~ Admit + Gender, data=UCB))
                  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
 > as.matrix(ftable(Dept ~ ., data=UCB))
                  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
 > as.matrix(ftable(Admit + Gender ~ Dept, data=UCB))
     Admit_Gender
Dept Admitted_Male Admitted_Female Rejected_Male Rejected_Female
    A           512              89 313              19
    B           353              17 207               8
    C           120             202 205             391
    D           138             131 279             244
    E            53              94 138             299
    F            22              24 351             317
 > as.matrix(ftable(Admit ~ ., data=UCB))
            Admit
Gender_Dept Admitted Rejected
    Male_A        512      313
    Male_B        353      207
    Male_C        120      205
    Male_D        138      279
    Male_E         53      138
    Male_F         22      351
    Female_A       89       19
    Female_B       17        8
    Female_C      202      391
    Female_D      131      244
    Female_E       94      299
    Female_F       24      317
 >
 > str(as.matrix(ftable(Admit + Gender ~ Dept, data=UCB)))
  num [1:6, 1:4] 512 353 120 138 53 22 89 17 202 131 ...
  - attr(*, "dimnames")=List of 2
   ..$ Dept        : chr [1:6] "A" "B" "C" "D" ...
   ..$ Admit_Gender: chr [1:4] "Admitted_Male" "Admitted_Female" 
"Rejected_Male" "Rejected_Female"
 >




On 1/9/2014 11:32 AM, William Dunlap wrote:
> 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.


-- 
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




More information about the R-help mailing list