[R] Cross Tables with odfTable in odfweave

Marc Schwartz marc_schwartz at comcast.net
Tue Mar 3 02:28:06 CET 2009


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