I am trying to automatically compile multiple individual PDF reports from RMarkdown using a for loop in a separate R script. There appears to be an issue using the kable_styling() function from the kableExtra package when compiling multiple reports, but not for a single report.
This is the render loop in a separate script:
mtcars = data.frame(mtcars)
for (car in unique(rownames(mtcars))){
rmarkdown::render('mtcars_report.Rmd', # file 2
output_file = paste("report_", car, ".pdf"))
}
Here is the YAML header used for all reports:
title: "mtcars_report"
output:
pdf_document: default
html_document:
df_print: paged
header-includes:
- \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[normalem]{ulem}
- \usepackage[utf8]{inputenc}
- \usepackage{makecell}
- \usepackage{xcolor}
geometry: margin=.8cm
This RMD code works with this loop and renders each PDF:
knitr::opts_chunk$set(echo = TRUE)
library(rmarkdown)
library(dplyr)
library(kableExtra)
mtcars = data.frame(mtcars)
cars = mtcars[rownames(mtcars)==car,]
{r, echo=FALSE, message=FALSE}
cars_table = cars %>%
select(mpg, cyl)%>%
t() %>%
kable("latex")
cars_table
This add a kable_styling command, the PDFs do not render:
cars_table = cars %>%
select(mpg, cyl)%>%
t() %>%
kable("latex") %>%
kable_styling(latex_options=c("striped", "float_right", "hold_position"),full_width = FALSE)
cars_table
I get this error: ! Undefined control sequence.
\rowcolor
If I knit the RMD as a single file without the loop (i.e. cars = mtcars[rownames(mtcars)=="Merc 280",] it DOES work with the kable_styling . It just appears to be an issue when I try to render it with the loop. I have updated all packages to my knowledge running:
update.packages(ask = FALSE, checkBuilt = TRUE) # update R packages
tinytex::tlmgr_update() # update LaTeX packages
Related
I am trying generate automated reports using rmarkdown, and final output expected is pdf. However, when I run the script the resulting .Rmd file is okay, but the resulting .pdf file does not show the table. It just shows the table as a list of values. However, if I open the .Rmd file in RStudio, and use the kint button, I get a correctly formatted pdf file. Has anyone seen this behaviour before? am I missing something?
---
title: "RUO"
author: "Me"
date: "`r format(Sys.Date(), '%B %d, %Y')`"
always_allow_html: true
output:
pdf_document:
df_print: kable
keep_tex: true
latex_engine: lualatex
header-includes:
- \usepackage{graphicx}
- \usepackage{fancyhdr}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage[para,flushleft]{threeparttable}
- \usepackage{fontspec}
- \setmainfont{Raleway}
- \AtBeginDocument{\let\maketitle\relax}
classoption:
- twocolumn
---
\fancypagestyle{plain}{}
\pagestyle{fancy}
\addtolength{\headheight}{1.0cm}
\rhead{Name: John Doe\\Sex: Male\\DoB: 01.01.01\\Lab \#: XXXXXXXX\\MRN \#: XXXXXXXX}
```{r setup, warning = FALSE, message = FALSE, echo = FALSE}
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE)
library(tidyverse)
library(stringi)
library(DESeq2)
library(kableExtra)
```
## This section is for Research Use Only
### Expression Table
```{r ExpTable}
df <- data.frame(cbind("gene_name" = c("AAA", "BBB", "CCC"),
"z-score" = c(-2, 2, 3)))
df %>%
setNames(c("Gene Name", "Z-score")) %>%
as.data.frame() %>%
# as_tibble() %>%
knitr::kable(booktabs = T) %>%
kableExtra::kable_styling(latex_options = c("hold_position", "striped")) # %>%
# kableExtra::column_spec(2, width = "3 cm")
```
\vfill
### Methodology
Some Description
### Comments and Limitations
Disclosures.
\clearpage
This code is the minimal example. When you use something like:
Rscript -e "library('knitr'); knitr::knit('filename.Rmd')"
The table does not render, but opening the same file in RStudio, renders is correctly.
UPDATE:
I realized after some more digging, that this is a un-reported bug (probably). If you render a rmarkdown with a table to pdf, then it will usually render correctly. But sometimes, the table is rendered as a list in the first render, and if you then render the same .Rmd to pdf, the table is rendered and correctly reformatted. So if you render the same file twice, the second time all the tables are correctly rendered. This happens more frequently if the only thing your file has a single table.
I know similar questions have been asked. However, I have tried all of those solutions as you will see in my code and none of them have worked. The strangest part is that my code has worked properly for months and only this week stopped working. The following code is within an RMD file and generates a table exactly as I want it when using the knit button on R Studio:
---
title: "Cars"
author: "xxx"
date: '`r format(Sys.Date(), "%B-%d-%Y")`'
always_allow_html: yes
output: pdf_document
classoption: portrait
header-includes:
- \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}
---
```{r}
library(kableExtra)
library(dplyr)
data <- cars
Portfolio <- c(4,7)
data%>%
mutate(
speed = cell_spec(speed, background= ifelse(speed %in% Portfolio, "yellow", "white"))
) %>%
kable(escape = F, longtable= T) %>%
kable_styling("striped", full_width = F, latex_options = "repeat_header")
```
The table looks like this:
It also continues into the next page.
I need to generate this report several times and so I have a separate R file where I loop the rendering of the previous code into separate PDF files.
# load packages
library(knitr)
library(rmarkdown)
library(kableExtra)
library(dplyr)
Portfolio <- c( 4,7)
# for each bond in the portfolio create a report
# these reports are saved in output_dir with the name specified by output_file
for (i in 1:length(Portfolio)){
Bond <- Portfolio[i]
rmarkdown::render("Table.Rmd" ,
output_format = "pdf_document",
output_file = paste(Bond, ".pdf", sep=''),
output_dir = paste('Reports_',format(Sys.Date(), "%b-%d-%y")),
envir = new.env(
Bond <- Portfolio[i]
))
}
This code renders the PDF and everything in my reports look the same with the exception of kableExtra tables. Here is a picture of what the table looks like now:
This is my first time asking a question on SO. I would appreciate any help for getting my code to work as well as advice on how to better format my questions in the future.
I think you need to specify the format (latex) for both the cell_spec and the kable calls. I don't really understand why but seems to work..
data %>%
mutate(
speed = cell_spec(speed, format = "latex", background= ifelse(speed %in% Portfolio, "yellow", "white"))
) %>%
kable(format = "latex", escape = F, longtable= T) %>%
kable_styling("striped", full_width = F, latex_options = "repeat_header")
I'm trying to knit a rmarkdown file to PDF file which contains kableExtra functions like:
kable_styling
column_spec
add_header_above
However I am always getting the following error:
! Extra alignment tab has been changed to \cr.
<template> \endtemplate
l.184 \end{tabular}}
pandoc.exe: Error producing PDF
Error: pandoc document conversion failed with error 43
EjecuciĆ³n interrumpida
One easy example that I am executing is:
```
---
output:
pdf_document:
keep_tex: yes
classoption: table
header-includes:
- \usepackage{array}
- \usepackage{float}
- \usepackage{xcolor}
---
```{r results='asis'}
options(kableExtra.latex.load_packages = FALSE)
require(kableExtra)
print(kable(head(cars),"latex")%>%kable_styling(latex_options = c("striped",
"bordered"))
%>%column_spec(column=1:2,width = "0.5in") %>%
kable_styling(c("striped", "bordered"),latex_options =
"scale_down")%>% add_header_above(c(" "=7,
"Absolute"=1,"Relative"=1,"Absolute"=1,"Relative"=1,
"Absolute"=1,"Relative"=1,"Absolute"=1,"Relative"=1,"Absolute"=1,
"Relative"=1))%>%
add_header_above(c(" "= 1,"Non-weighted"=1,"Weighted"=1,"Non-
weighted"=1,"Weighted"=1,"Non-weighted"=1,
"Weighted"=1,"Weighted"=2,"Non-weighted"=2,"Weighted"=2,"Non-
weighted"=2,"Weighted"=2))%>%
add_header_above(c("Theoretical Values"= 1,"First-Order Predicted
Value"=2,"Second-Order Predicted Value"=2,
"Third-Order Predicted Value"=2,
"Non-linearity 1st Order"=2,"Non-linearity 2nd Order"=4,"Non-linearity 3rd
Order"=4)))
```
Can anyone help me with this issue?
I would appreciate whatever clue!
You are telling kableExtra not to load the LaTeX packages (why?), so you have to do this yourself. The features you are using require array, float and xcolor with the table option. One difficulty is that fancyvrb v3.0 already loads xcolor with other options. You can circumvent this by supplying table as a class option:
---
output:
pdf_document:
keep_tex: yes
classoption: table
header-includes:
- \usepackage{array}
- \usepackage{float}
---
```{r results='asis'}
options(kableExtra.latex.load_packages = FALSE)
require(kableExtra)
print(kable(head(cars),"latex") %>%column_spec(column=1:2,width = "0.5in"))
```
```{r results='asis'}
print(kable(head(cars),"latex")%>%kable_styling(latex_options = c("striped", "bordered")))
```
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.
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}}