[R] Cross Tables with odfTable in odfweave

Paul Jones raptorman18 at gmail.com
Mon Mar 9 07:20:24 CET 2009


Hey Marc,

Your code was very helpful. You should make a new R function out of it.

Actually it looks like adding margins may be a little bit tricky if I 
only want sums of the counts, not the percentages. If I add margins 
after I rbind, then R will sum together the counts with the 
probabilities, which is undesired. If I add margins before I rbind which 
is what I've been doing, it will produce sums of the counts and 
percentages independently but this still gives me sums of probabilities 
that are pretty useless and confusing in the table.

I'm actually running into bigger trouble trying to put the for loop I 
want into odfweave.

If I use odfweave, the odfweave function produces an output file, but 
the for loop produces no tables. If I use R2HTML with similar code, I 
just get the last table the for loop produces. Here is a look at the 
code of odfweave, which seems to be correct with syntax but doesn't 
produce any tables.

<<CrossTable, echo = FALSE, results = xml>>=

# Generate counts and proportions
# row, column and table
for ( i in 5:ncol(Elementary)[1] ) {

TAB <- table(Elementary[["Curriculum"]], Elementary[,i])
TAB.prop.c <- prop.table(table(Elementary[["Curriculum"]], 
Elementary[,i]),2)


TAB <- addmargins(TAB)
TAB.prop.c <- addmargins(TAB.prop.c)

MAT.3 <- t(apply(rbind(TAB.prop.c), 1,
                 function(x) sprintf("%.3f", x)))

MAT <- rbind(TAB, MAT.3)

# order by rownames
MAT <- MAT[order(rownames(MAT)), ]

# Set duplicated rownames to blank
rownames(MAT)[which(duplicated(rownames(MAT)))] <- ""

odfTable(MAT)
}
@

Sorry for bugging everyone with a question that is probably simple. Also 
is there  a way to add a table title in the odfTable function.

Thanks again,
PJ

Marc Schwartz wrote:
> on 03/02/2009 03:11 PM Max Kuhn wrote:
>   
>> PJ,
>>
>>     
>>> Hi, I've been trying to prepare some crosstables for some survey questions
>>> for a client. I have been using the CrossTable function in the gmodels
>>> package. However, this command only seems to be able to create CrossTables
>>> in text documents.
>>>
>>> I've been trying to use odfTable in odfweave to create tables that are
>>> standalone objects in the document that I can then convert to other formats,
>>> copy and paste and do whatever with.
>>>       
>> You will have to do some work to get CrossTable results into odfWeave
>> for a few reasons. The main one is: CrossTable prints the output (as
>> opposed to outputting an object of a certain class that uses print to
>> make the results like table() and print.table()). In some cases, it is
>> easy to translate the output you see on the screen to odf markup. I'm
>> not sure that this function is one of those cases. That is not a
>> slight against the function, it just isn't meant to do that.
>>
>>     
>>> The problem is no matter how I try to get the CrossTable into the odfTable,
>>> i either get an error message saying there is no appropriate method for
>>> odfTable or the table is inproperly formatted.
>>>       
>> It would be nice to have a reproducible example along with the results
>> of sessionInfo(). Looking at ?odfTable, it has that the main argument
>> should be "a vector, matrix or data frame". I can' tell if there is a
>> bug in odfTable or if you are just using it incorrectly.
>>
>>     
>>> Honestly, I'm not even married to using odfTable. All I'm looking for is a
>>> nicely formatted table, that is a standalone object, that I can copy and
>>> paste and convert at will, and that contains the column percentages in the
>>> table.
>>>       
>> CrossTable may not be what you want then. The results are a list of
>> components of the table.
>>     
>
> In follow up to Max' post, if you can output or print the captured
> CrossTable() content in odfWeave to a monospaced font, it would line up
> appropriately. The use of a monospace font in the R console is the
> presumption for CrossTable() output. However, it will look exactly as it
> would in the R console (see below) as opposed to something more
> formalized and "pretty".
>
> You could largely recreate most of CrossTable's output using table() and
> prop.table() by creating a matrix or dataframe, depending upon what you
> want things to look like. This is what is essentially done within
> CrossTable().
>
> Using one of the examples in ?CrossTable:
>
>
>   
>> CrossTable(infert$education, infert$induced, prop.chisq = FALSE)
>>     
>
> ...
>
>                  | infert$induced
> infert$education |         0 |         1 |         2 | Row Total |
> -----------------|-----------|-----------|-----------|-----------|
>           0-5yrs |         4 |         2 |         6 |        12 |
>                  |     0.333 |     0.167 |     0.500 |     0.048 |
>                  |     0.028 |     0.029 |     0.162 |           |
>                  |     0.016 |     0.008 |     0.024 |           |
> -----------------|-----------|-----------|-----------|-----------|
>          6-11yrs |        78 |        27 |        15 |       120 |
>                  |     0.650 |     0.225 |     0.125 |     0.484 |
>                  |     0.545 |     0.397 |     0.405 |           |
>                  |     0.315 |     0.109 |     0.060 |           |
> -----------------|-----------|-----------|-----------|-----------|
>          12+ yrs |        61 |        39 |        16 |       116 |
>                  |     0.526 |     0.336 |     0.138 |     0.468 |
>                  |     0.427 |     0.574 |     0.432 |           |
>                  |     0.246 |     0.157 |     0.065 |           |
> -----------------|-----------|-----------|-----------|-----------|
>     Column Total |       143 |        68 |        37 |       248 |
>                  |     0.577 |     0.274 |     0.149 |           |
> -----------------|-----------|-----------|-----------|-----------|
>
>
>
> # Do the above incrementally
> # Generate counts and proportions
> # row, column and table
> TAB <- table(infert$education, infert$induced)
> TAB.prop.r <- prop.table(table(infert$education, infert$induced), 1)
> TAB.prop.c <- prop.table(table(infert$education, infert$induced), 2)
> TAB.prop.t <- prop.table(table(infert$education, infert$induced))
>
> # rbind() it all together
> MAT <- rbind(TAB, TAB.prop.r, TAB.prop.c, TAB.prop.t)
>
> # order by rownames
> MAT <- MAT[order(rownames(MAT)), ]
>
> # Set duplicated rownames to blank
> rownames(MAT)[which(duplicated(rownames(MAT)))] <- ""
>
>
>   
>> MAT
>>     
>                   0            1           2
> 0-5yrs   4.00000000  2.000000000  6.00000000
>          0.33333333  0.166666667  0.50000000
>          0.02797203  0.029411765  0.16216216
>          0.01612903  0.008064516  0.02419355
> 12+ yrs 61.00000000 39.000000000 16.00000000
>          0.52586207  0.336206897  0.13793103
>          0.42657343  0.573529412  0.43243243
>          0.24596774  0.157258065  0.06451613
> 6-11yrs 78.00000000 27.000000000 15.00000000
>          0.65000000  0.225000000  0.12500000
>          0.54545455  0.397058824  0.40540541
>          0.31451613  0.108870968  0.06048387
>
>
> So that gives you the core table with counts, table, row and column
> proportions in that order top to bottom for each row category as in
> CrossTable(). Adjust the above based upon what you actually want in the
> table output.
>
> With some additional work, you could add row and column totals and so
> forth.
>
> If you wanted variable numbers of digits after the decimal for each row
> as in CrossTable(), you could pre-format the numbers using sprintf(),
> converting MAT to a character matrix in the process. For example:
>
> MAT.3 <- t(apply(rbind(TAB.prop.r, TAB.prop.c, TAB.prop.t), 1,
>                  function(x) sprintf("%.3f", x)))
>
> MAT <- rbind(TAB, MAT.3)
>
> # order by rownames
> MAT <- MAT[order(rownames(MAT)), ]
>
> # Set duplicated rownames to blank
> rownames(MAT)[which(duplicated(rownames(MAT)))] <- ""
>
>   
>> MAT
>>     
>         0       1       2
> 0-5yrs  "4"     "2"     "6"
>         "0.333" "0.167" "0.500"
>         "0.028" "0.029" "0.162"
>         "0.016" "0.008" "0.024"
> 12+ yrs "61"    "39"    "16"
>         "0.526" "0.336" "0.138"
>         "0.427" "0.574" "0.432"
>         "0.246" "0.157" "0.065"
> 6-11yrs "78"    "27"    "15"
>         "0.650" "0.225" "0.125"
>         "0.545" "0.397" "0.405"
>         "0.315" "0.109" "0.060"
>
>
>
> With 'MAT' finalized, you could then use Max' functions to generate
> pretty output for an OO.org document or use xtable() in the xtable
> package or latex() in the Hmisc package for LaTeX or perhaps HTML output.
>
> HTH,
>
> Marc Schwartz
>
>
>




More information about the R-help mailing list