-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path04-tables.Rmd
242 lines (186 loc) · 7.4 KB
/
04-tables.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
---
output:
#bookdown::html_document2: default
#bookdown::word_document2: default
bookdown::pdf_document2:
template: templates/brief_template.tex
citation_package: biblatex
documentclass: book
#bibliography: [bibliography/references.bib, bibliography/additional-references.bib]
---
# Tables {#tables}
\minitoc <!-- this will include a mini table of contents-->
## Making LaTeX tables play nice
Dealing with tables in LaTeX can be painful.
This section explains the main tricks you need to make the pain go away.
(Note: if you are looking at the ebook version, you will not see much difference in this section, as it is only relevant for PDF output!)
Two package options are described, `flextable` and `kable`/`kableExtra`.
While the `flextable` package is optomised for Word output, it also produces great PDF and html tables.
Also, tables produced by `kable` are not readable in Word output.
### flextable {#flextable}
Below is a basic flextable example.
See also some simple setup steps in `index.Rmd` to set global flextable options (such as using the default latex font).
```{r, message=FALSE}
library(flextable)
library(tidyverse)
head(mtcars) %>%
flextable()
```
Now including rownames and setting the table width to 6 inches:
```{r}
head(mtcars) %>%
rownames_to_column() %>%
flextable() %>%
set_header_labels("rowname" = "") %>%
width(width = 0.5)
```
You may find it particularly handy to use `flextable` together with `tbl_summary()` and `tbl_regression` from the `gtusmmary` package.
```{r tbl-summary-flextable}
library(gtsummary,
warn.conflicts = FALSE)
trial %>%
select(trt, age, grade) %>%
tbl_summary(by = trt) %>%
bold_labels() %>%
add_p() %>%
as_flex_table() %>%
bold(part = "header") %>%
width(width = 1.5) %>%
set_caption("A 'table 1' example.")
```
```{r tbl-regression-flextable}
# build logistic regression model
m1 <- glm(response ~ age + stage, trial, family = binomial)
tbl_regression(m1,
exponentiate = TRUE) %>%
bold_labels() %>%
as_flex_table() %>%
width(width = 1.5) %>%
italic(i = 1,
j = 4) %>%
highlight(i = 1,
j = 4,
color = "yellow") %>%
bold(part = "header") %>%
set_caption("A regression model example with an *italicised* and yellow highlighted p value.")
```
Some other tips:
- Note the use of `set_caption()`, which enables cross referencing (e.g. Table \@ref(tab:tbl-regression-flextable)) and adds the table to the list of tables (near the start of PDF output).
- For landscape tables, use the latex commands 'begin{landscape}' and 'end{landscape}' (see example Table \@ref(tab:landscape-table)).[^tables-1]
- For html and Word output the `flextable` autofit options may be preferable to manually specifying table dimensions (see example Tables \@ref(tab:landscape-table) and \@ref(tab:long-flextable)).
- For long tables, the header will be repeated at the top of each new page (see example Table \@ref(tab:long-flextable))
[^tables-1]: This only seems to work with chunk option `echo=FALSE`.
`r if(knitr::is_latex_output()) {"\\begin{landscape}"}`
```{r landscape-table, echo=FALSE}
tab <- head(mtcars) %>%
rownames_to_column() %>%
flextable() %>%
set_header_labels("rowname" = "") %>%
set_caption("An example landscape flextable table.")
if (knitr::is_latex_output()) {
tab %>%
width(width = 0.75)
} else if (knitr::is_html_output()) {
tab %>%
autofit()
} else {
tab %>%
set_table_properties(layout = "autofit")
}
```
`r if(knitr::is_latex_output()) {"\\end{landscape}"}`
```{r long-flextable}
tab <- mtcars %>%
rownames_to_column() %>%
select(1:8) %>%
flextable() %>%
set_header_labels("rowname" = "") %>%
set_caption("A long flextable.")
if (knitr::is_latex_output()) {
tab %>%
width(width = 0.75)
} else if (knitr::is_html_output()) {
tab %>%
autofit()
} else {
tab %>%
set_table_properties(layout = "autofit")
}
```
### kable/kableExtra
#### Making your table pretty
When you use `kable` to create tables, you will almost certainly want to set the option `booktabs = TRUE`.
This makes your table look a million times better:
```{r, message=FALSE}
library(knitr)
head(mtcars) %>%
kable(booktabs = TRUE)
```
\vspace{4mm}
Compare this to the default style, which looks terrible:
```{r}
head(mtcars) %>%
kable()
```
#### If your table is too wide
You might find that your table expands into the margins of the page, like the tables above.
Fix this with the `kable_styling` function from the [`kableExtra`](https://haozhu233.github.io/kableExtra/) package:
```{r, message=FALSE}
library(kableExtra)
head(mtcars) %>%
kable(booktabs = TRUE) %>%
kable_styling(latex_options = "scale_down")
```
This scales down the table to fit the page width.
#### If your table is too long
If your table is too long to fit on a single page, set `longtable = TRUE` in the `kable` function to split the table across multiple pages.
```{r}
a_long_table <- rbind(mtcars, mtcars)
a_long_table %>%
select(1:8) %>%
kable(booktabs = TRUE, longtable = TRUE)
```
When you do this, you'll probably want to make the header repeat on new pages.
Do this with the `kable_styling` function from `kableExtra`:
```{r}
a_long_table %>%
kable(booktabs = TRUE, longtable = TRUE) %>%
kable_styling(latex_options = "repeat_header")
```
Unfortunately, we cannot use the `scale_down` option with a `longtable`.
So if a `longtable` is too wide, you can either manually adjust the font size, or show the table in landscape layout.
To adjust the font size, use kableExtra's `font_size` option:
```{r}
a_long_table %>%
kable(booktabs = TRUE, longtable = TRUE) %>%
kable_styling(font_size = 9, latex_options = "repeat_header")
```
To put the table in landscape mode, use kableExtra's `landscape` function:
```{r}
a_long_table %>%
kable(booktabs = TRUE, longtable = TRUE) %>%
kable_styling(latex_options = "repeat_header") %>%
landscape()
```
#### Max power: manually adjust the raw LaTeX output {#max-power}
For total flexibility, you can adjust the raw LaTeX output from `kable`/`kableExtra` that generates the table.
Let us consider how we would do this for the example of adjusting the font size if our table is too wide: Latex has a bunch of standard commands that set an approximate font size, as shown below in Figure \@ref(fig:latex-font-sizing).
```{r latex-font-sizing, echo=FALSE, out.width='50%', fig.cap="Font sizes in LaTeX", fig.pos="H", fig.align='center'}
knitr::include_graphics("figures/sample-content/latex_font_sizes.png")
```
You could use these to manually adjust the font size in your longtable in two steps:
1. Wrap the longtable environment in, e.g., a `scriptsize` environment, by doing a string replacement in the output from `kable`/`kableExtra`
2. Add the attributes that make R Markdown understand that the table is a table (it seems R drops these when we do the string replacement)
```{r}
our_adjusted_table <- a_long_table %>%
kable(booktabs = TRUE, longtable = TRUE) %>%
kable_styling(latex_options = "repeat_header") %>%
# wrap the longtable in a tiny environment
str_replace('\\\\begin\\{longtable\\}',
'\\\\begin\\{scriptsize\\}\n\\\\begin\\{longtable\\}') %>%
str_replace('\\\\end\\{longtable\\}',
'\\\\end\\{longtable\\}\n\\\\end\\{scriptsize\\}')
#add attributes to make R Markdown treat this as a kable LaTeX table again
our_adjusted_table %>%
structure(format = "latex", class = "knitr_kable")
```