how to cross reference tables and plots in rmarkdown? - r

I am using the following template
---
title: "Nice try buddy"
author: "SpaceMan"
date: "13 December 2057"
output:
bookdown::pdf_document2
header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage[table]{xcolor}
- \usepackage{wrapfig}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage{pdflscape}
- \usepackage{tabu}
- \usepackage{threeparttable}
- \usepackage{threeparttablex}
- \usepackage[normalem]{ulem}
- \usepackage{makecell}
---
---
references:
- id: fenner2012a
title: One-click science marketing
container-title: Nature Materials
volume: 11
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## Title
\begin{equation}
f\left(k\right)=\binom{n}{k}p^k\left(1-p\right)^{n-k} \label{eq:binom}
\end{equation}
You may refer to it using `\#ref(eq:binom)`, e.g., see Equation \#ref(eq:binom).
and not a nice citation! #fenner2012a
## Including Tables
You can also embed tables, for example: \#ref(tab:tw)
```{r tw, echo=FALSE}
mytable
```
## References
where mytable is stored in R session and is generated with
mytable <- head(cars) %>% kable(format = "latex",
booktabs = T,
caption = "Demo Table",
escape = F) %>%
kable_styling(latex_options = 'HOLD_position')
Now, this is supposed to work, but when I knit the document using
rmarkdown::render('C:\\Users\\john\\Documents\\bbv.Rmd')
the cross-reference for the table is not there! I only see ??
and the table has this weird #tab thing - how to get rid of it ?
the TOC is here even though I did not ask for it
Any ideas how to fix these issues?
Thanks!
EDIT: the weird #tab thing disappeared after a reboot.

The problem is that you are working against the intentions of kable by using it outside of an R chunk:
The kable() function will automatically generate a label for a table environment, which is the prefix tab: plus the chunk label.
https://bookdown.org/yihui/bookdown/tables.html
So the following workaround is definitely on the hacky side. Using a file foo.Rmd with
---
output:
bookdown::pdf_document2:
toc: no
header-includes:
- \usepackage{float}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## Including Tables
You can also embed tables, for example: \#ref(tab:tw)
```{r tw, echo=FALSE}
mytable
```
You can also embed tables, for example: \#ref(tab:tw2)
```{r tw2, echo=FALSE}
mytable2
```
Referencing images is easier: \#ref(fig:plt)
```{r plt, echo=FALSE, fig.cap = 'hello', fig.height=3}
myplot
```
one can process this file with a second file foo.R:
library(knitr)
library(kableExtra)
# add the label to the options that would normally be populated from the chunk options
opts_current$append(list(label = "tw"))
mytable <- head(cars) %>% kable(format = "latex",
booktabs = T,
caption = "Demo Table",
escape = F) %>%
kable_styling(latex_options = 'HOLD_position')
opts_current$restore()
opts_current$append(list(label = "tw2"))
mytable2 <- tail(cars) %>% kable(format = "latex",
booktabs = T,
caption = "Demo Table",
escape = F) %>%
kable_styling(latex_options = 'HOLD_position')
opts_current$restore()
myplot <- ggplot(cars, aes(x = dist, y = speed)) + geom_point()
rmarkdown::render("foo.Rmd")
In principle, you can do these commands also just at the R prompt, but I try to not use the prompt directly. BTW, I do not get the (#tab) output with your code.
However, I think it makes more sense to not work against the workings of kable. I can understand that it can make sense to separate the data manipulation fro the presentation. However, creating the table is presentation from my point of view. So instead of creating the table externally I would just create the data externally. To make this concrete, let's use a file bar.Rmd:
---
output:
bookdown::pdf_document2:
toc: no
header-includes:
- \usepackage{float}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(kableExtra)
```
## Including Tables
You can also embed tables, for example: \#ref(tab:tw)
```{r tw, echo=FALSE}
mydata %>% kable(format = "latex",
booktabs = T,
caption = "Demo Table",
escape = F) %>%
kable_styling(latex_options = 'HOLD_position')
```
together with a file bar.R:
# insert data processing here
mydata <- head(cars)
rmarkdown::render("bar.Rmd")
This gives me the same output and the data processing is (initially!) separated from the presentation.

Related

Rotate table pdf output from Markdown

I want to rotate table output by 90 degrees on pdf. I am using markdown to generate a report and kable to display the tables in a loop. If possible, I would like to continue using kable since there are lot of other things which are dependent on it that I haven't included in this MWE.
This is a simple example using iris dataset. I tried using landscape function from this post Rotate a table from R markdown in pdf
---
output: pdf_document
header-includes:
\usepackage{lscape}
\usepackage{pdfpages}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
Report page -
```{r results='asis'}
library(knitr)
library(kableExtra)
for (i in 1:3) {
print(landscape(kable_styling(
kable(iris[i:(i+5), ], format = "latex", align = "c", booktabs = TRUE,
longtable = TRUE, row.names = FALSE), latex_options = c("striped"), full_width = T)))
}
```
But this only rotates the page number keeping the table as it is.
I am actually looking for a solution which provides me the output in this way -
To clarify, all the pages with table data in it (3 for this example) should be rotated whereas rest of them should remain as it is. Also, I need longtable = TRUE in kable since in my actual example I am printing lot of rows.
Use package rotating
I added a simple example for you.
---
title: "test"
header-includes: \usepackage[figuresright]{rotating}
#or \usepackage[figuresleft]{rotating}
output:
pdf_document:
latex_engine: xelatex
---
```{r setup, include = FALSE}
library(flextable)
ft <- flextable(head(mtcars))
```
\begin{sidewaysfigure}
`r ft`
\end{sidewaysfigure}
```
Further you can modify it for your tasks ;)
I found another way using rotatebox.
---
output: pdf_document
header-includes:
\usepackage{lscape}
\usepackage{pdfpages}
\usepackage{graphicx}
\usepackage[figuresright]{rotating}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
Report page -
```{r results='asis', warning=FALSE, message=FALSE}
library(knitr)
library(kableExtra)
for (i in 1:3) {
cat('\\rotatebox{90}{')
print(kable(iris[i:(i+5), ], format = "latex", align = "c", booktabs = TRUE,
row.names = FALSE))
cat('}')
cat("\n\\newpage\n")
}
```

Highlight table entry of a kable table upon clicking in a rmarkdown::beamer_presentation

In a LaTex beamer presentation generated with rmarkdown::beamer_presentation, is there a way to highlight the content of a specific cell of a kableExtra table upon clicking?
MWE
---
output:
bookdown::pdf_book:
base_format: rmarkdown::beamer_presentation
latex_engine: xelatex
slide_level: 2
---
```{r}
library(dplyr)
library(kableExtra)
```
## Table
```{r table, echo = FALSE}
my_df <- mtcars[1:4, 1:2]
my_table <- kable(my_df, booktabs = T, caption = "Table caption")
my_table
```
The proposed solution uses kableExtra's row_spec/column_spec/cell_spec functionality, for which several LaTex packages have to be loaded (e.g., via header-includes: ...).
The solution works with only one little thing remaining: the table numeration increases.
That is, the table on the first frame is numbered "1" and on the second frame with "2".
To make things really look like the added color is the only difference between both frames, the numeration would ideally be the same for both tables.
To color the rows/columns/cells as you need, see also the rmarkdown cookbook for more info on how to use row_spec/column_spec/cell_spec.
---
output:
bookdown::pdf_book:
base_format: rmarkdown::beamer_presentation
latex_engine: xelatex
slide_level: 2
header-includes:
- \usepackage{booktabs}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage{wrapfig}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage{pdflscape}
- \usepackage{tabu}
- \usepackage{threeparttable}
- \usepackage{threeparttablex}
- \usepackage[normalem]{ulem}
- \usepackage{makecell}
---
```{r include=FALSE}
library(dplyr)
library(kableExtra)
```
## Table
```{r table, echo = FALSE}
my_df <- mtcars[1:4, 1:2]
my_table <- kable(my_df, booktabs = T, caption = "Table caption")
my_table
```
## Table {.noframenumbering}
<!-- Add "{.noframenumbering}" such that the frame number is the same on both frames -->
```{r table-with-colored-cell, echo = FALSE}
special_cell <- c(rep(F, 3), T)
colors_of_column_with_special_cell <- c(rep("black", 3), "red")
my_table %>%
column_spec(2, strikeout = special_cell, bold = special_cell, color = colors_of_column_with_special_cell)
```

Is there a way to unify the numbering of tables caption in r markdown to html in r via `kable()` and `htmltable()`?

When I want to print some tables in html report from knitr, sometime I use knitr::kable(), and other times I use htmltable::htmltable.
When I use bookdown::html_document2 in the YAML numbering of tables from kable is automatic. However, it is not for htmltable, and I need to use options(table_counter = TRUE), which generates another numbering mechanism. Is there a way to unify it?
Example:
---
title: "Untitled"
author: "Guilherme"
date: "10/26/2020"
output:
bookdown::html_document2
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
options(table_counter = TRUE)
```
```{r cars}
library(htmlTable)
htmlTable(mtcars[1:5,1:5],
caption = "XX")
```
```{r}
htmlTable(mtcars[1:5,1:5],
caption = "XX")
```
```{r}
library(knitr)
kable(mtcars[1:5,1:5],
caption = "XX")
```
Outputs:
Thanks!

Rmarkdown Beamer repeat table header across multiple pages

I am building a beamer presentation in rmarkdown and I have a long table that I create using kable and kableExtra, and splitting between two slides. I have been able to split the table fine, but I am having trouble getting the header to repeat. The solutions I have found on the Tex stackexchange pages suggest using different packages, or manually splitting the table in the Tex file. I don't think the additional package suggested, xtab, is compatible with kableExtra. Here is and example of what I am working on.
---
title: Title
author: James
classoption: table
output:
beamer_presentation:
keep_tex: true
includes:
in_header: ./R presentaion/header.tex
---
```{r setup, include=FALSE}
library(knitr)
library(kableExtra)
library(magrittr)
options(knitr.kable.NA = '')
```
```{r, echo=FALSE}
long_dt <- rbind(mtcars, mtcars)
```
#Slide {.allowframebreaks}
```{r, echo=FALSE, results='asis'}
kable(mtcars, format = "latex", longtable = TRUE, booktabs = TRUE) %>%
add_header_above(c(" ", "Group 1" = 5, "Group 2" = 6)) %>%
kable_styling(latex_options = c("striped", "repeat_header"), font_size = 6)
```
This is what the template file looks like.
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{array}
\usepackage{multirow}
\usepackage{wrapfig}
\usepackage{float}
\usepackage{colortbl}
\usepackage{pdflscape}
\usepackage{tabu}
\usepackage{threeparttable}
\usepackage{threeparttablex}
\usepackage[normalem]{ulem}
\usepackage{makecell}
\usepackage{xcolor}
\usepackage{xtab}
\def\begincols{\begin{columns}}
\def\begincol{\begin{column}}
\def\endcol{\end{column}}
\def\endcols{\end{columns}}
\def\begincols{\begin{columns}}
\def\begincol{\begin{column}}
\def\endcol{\end{column}}
\def\endcols{\end{columns}}

Align multiple tables side by side

The following code produces 2 tables on top of each other. How would I set it to have them aligned side by side, e.g. 3 to a row?
---
title: "sample"
output: pdf_document
---
```{r global_options, R.options=knitr::opts_chunk$set(warning=FALSE, message=FALSE)}
```
```{r sample, echo=FALSE, results='asis'}
library(knitr)
t1 <- head(mtcars)[1:3]
t2 <- head(mtcars)[4:6]
print(kable(t1))
print(kable(t2))
```
Output looks like this:
Just put two data frames in a list, e.g.
t1 <- head(mtcars)[1:3]
t2 <- head(mtcars)[4:6]
knitr::kable(list(t1, t2))
Note this requires knitr >= 1.13.
I used this Align two data.frames next to each other with knitr? which shows how to do it in html and this https://tex.stackexchange.com/questions/2832/how-can-i-have-two-tables-side-by-side to align 2 Latex tables next to each other. It seems that you cannot freely adjust the lines of the table as you can do it with xtable (does anybody know more about this?). With format = Latex you get a horizontal line after each row. But the documentation shows two examples for other formats. One using the longtable package (additional argument: longtable = TRUE) and the other using the booktabs package (booktabs = TRUE).
---
title: "sample"
output: pdf_document
header-includes:
- \usepackage{booktabs}
---
```{r global_options, R.options=knitr::opts_chunk$set(warning=FALSE, message=FALSE)}
```
```{r sample, echo=FALSE, results='asis'}
library(knitr)
library(xtable)
t1 <- kable(head(mtcars)[1:3], format = "latex", booktabs = TRUE)
t2 <- kable(head(mtcars)[4:6], format = "latex", booktabs = TRUE)
cat(c("\\begin{table}[!htb]
\\begin{minipage}{.5\\linewidth}
\\caption{}
\\centering",
t1,
"\\end{minipage}%
\\begin{minipage}{.5\\linewidth}
\\centering
\\caption{}",
t2,
"\\end{minipage}
\\end{table}"
))
```
here a solution for html documents
(As this question was asked very broadly and not specifically referring to LaTeX).
Requires knitr and kableExtra
---
title: "Side by side"
output: html_document
---
```{r sample, echo=FALSE}
library(knitr)
library(kableExtra)
t1 <- head(mtcars)[1:3]
t2 <- head(mtcars)[4:6]
```
## as list
```{r}
kable(list(t1, t2))
```
## with float
```{r, echo = FALSE}
kable(t1) %>%
kable_styling(full_width = FALSE, position = "float_left")
kable(t2) %>%
kable_styling(full_width = FALSE, position = "left")
```
It is intentional that table t2 gets position = "left". If you allow it to float, this will not block the rest of the paragraph and mess up the following lines in your document.
result:
In Quarto, you can use layout-ncol. This works both for HTML and PDF outputs.
---
title: "sidebyside"
format: pdf
editor: visual
---
```{r}
#| layout-ncol: 2
#| tbl-cap: "Tables"
#| tbl-subcap: ["A table", "Another table"]
library(knitr)
# table on the left
kable(head(mtcars))
# table on the right
kable(head(cars))
```

Resources