Printing nice cross-tabulations in knitr
Asked Answered
C

4

18

What I want is to print nice crosstabulations, either in a pdf file, or in a html file, from RStudio, using R, Markdown and knitr. I suspect I am missing something really obvious, because I cannot believe this is so hard. I make cross-tabs with either xtabs or ftable.

What I want is something like a nicely printed version of the R console output.

> x
   Col
Row  A  B  C
  D 15  9  7
  E 13 14  9
  F  8  8 17
> f
    Col  A  B  C
Row             
D       15  9  7
E       13 14  9
F        8  8 17

I've tried several different solutions, none of which really works, and are shown in the attached .Rmd file. (I've tried pdf and html outputs.)

---
title: "trial"
author: "Anthony Staines"
date: "26/08/2014"
output: html_document
---
# Make the data
```{r, echo=TRUE,results='asis',message=FALSE}
library(knitr)
library(memisc)
library(xtable)
library(stargazer)
library(texreg)

set.seed(893)
Col <- sample(c('A','B','C'),100,replace=TRUE)
Row <- sample(c('D','E','F'),100,replace=TRUE)
```

```{r, echo=TRUE,results='asis',message=FALSE}
x <- xtabs(~Row+Col)
x
kable(x)
kable(x,format='html')
kable(x,format='html',output = TRUE)
xx <- xtable(format(x))
print(xx,type='html')
stargazer(x)

f <-ftable(Row,Col)
f
kable(f,format='html')
kable(f,format='html',output = TRUE)
xf <- xtable(format(f))
print(xf,type='html')
stargazer(f)
```

kable comes closest, but does not seem to support row or column names, both of which are essential to me :-

|   |  A|  B|  C|
|:--|--:|--:|--:|
|D  | 15|  9|  7|
|E  | 13| 14|  9|
|F  |  8|  8| 17|

Help appreciated, and my apologies if this is a really stupid question with an obvious and well known answer!

Anthony Staines

Cobaltous answered 26/8, 2014 at 22:59 Comment(2)
kable() does support column names; regarding row names, it does not seem to be a standard component of a table in either HTML or LaTeX, so it is unclear what "support" really means.Cohort
I agree that neither html nor latex directly support such labels, but for cross-tabs to make sense both are needed. The requirement is to produce a table usable to put into a journal article.What I actually do now is take the R console output, and turn into a table using the Table -> Convert -> Text to Table functions in Libre-Office, but this is not terribly repeatable!Cobaltous
F
8

An alternative to kable is pander from the package with the same name, which provides an easy way of generating markdown tables with bunch of options (like style) and a generic S3 method:

> pander(x)

-------------------
&nbsp;   A   B   C 
------- --- --- ---
 **D**  15   9   7 

 **E**  13  14   9 

 **F**   8   8  17 
-------------------

> pander(f)

----- ----- --- --- ---
      "Col" "A" "B" "C"

"Row"                  

 "D"        15   9   7 

 "E"        13  14   9 

 "F"         8   8  17 
----- ----- --- --- ---

If you want to generate the old rmarkdown-style pipe tables, add stlye='rmarkdown' parameter, although AFAIK Pandoc is the new standard there as well, which supports the above multi-line table.

Feathery answered 27/8, 2014 at 11:41 Comment(3)
Tried this out and it works beautifully - thank you for the guidance, much appreciated!Cobaltous
pander gives me an error "Error in if (!has.rownames(df)) { : missing value where TRUE/FALSE needed"Sanyu
pader::pander() rules for printing cross-tables. Thank you developers.Squashy
K
7

I suggest you use stargazer as follows:

  • Use quote=FALSE
  • Make sure to specify type="html"

Try this:

# stargazer

```{r, echo=TRUE, results='asis'}
stargazer(format(f, quote=FALSE, justify="right"), type="html")
```

enter image description here

Kingfish answered 27/8, 2014 at 11:19 Comment(1)
Tried this too and it also works beautifully - thank you for the guidance, much appreciated!Cobaltous
C
3

Further digging led me to this question.

The answer is embarrassingly obvious - the 'tables' package!

I thought there had to be a simpler way to do this. Many thanks nonetheless to Andrie and daroczig for their helpful responses.

Cobaltous answered 1/9, 2014 at 20:39 Comment(2)
If you know your output is going to be LaTeX only, it is relatively easy to produce a sophisticated table, otherwise this is not a trivial problem. It is difficult to achieve portability (a complicated table that works in Markdown, HTML, LaTeX, and other formats).Cohort
I'm beginning to appreciate this! What you've done already is very impressive, so please accept my thanks for all your work.Cobaltous
T
2

Consider tbl_cross from the gtsummary package:

library(gtsummary)

set.seed(893)
adf <- data.frame(Col = sample(c('A','B','C'),100,replace=TRUE),
                  Row = sample(c('D','E','F'),100,replace=TRUE))
tbl_cross(adf, row=Row, col=Col, percent="row")

gtsummary tbl_cross HTML crosstab example

Torture answered 19/1, 2021 at 16:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.