Shiny to Markdown PDF Fails on Second and Subsequent Runs - r

I've been trying to follow this tutorial: generating reports
I've been able to get the suggested code to run successfully and produces PDFs without issue. When I try to run the Shiny app using my own .Rmd file, it works fine the first time and produces a PDF where desired. On the second and any additional runs, the file generation fails with ! LaTeX Error: Unknown float option 'H'.
I've tried mentioning the {float} package in the YAML header of the markdown file without any improvement. The only success seems to be removing all of the r code blocks, which leaves my document looking pretty sparse.
Here is app.R:
shinyApp(
ui = fluidPage(
sliderInput("slider", "Slider", 1, 100, 50),
dateInput("dateinput", "Select a date"),
downloadButton("report.pdf", "Generate report")
),
server = function(input, output) {
output$report.pdf <- downloadHandler(
filename = "report.pdf",
content = function(file) {
tempReport <- file.path(tempdir(), "deviants.Rmd")
file.copy("deviants.Rmd", tempReport, overwrite = TRUE)
params <- list(n = input$slider, d = input$dateinput)
print(class(params$n))
print(class(params$d))
print(params)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
and deviants.Rmd:
---
output: pdf_document
always_allow_html: yes
params:
n: NA
d: NA
header-includes:
- \usepackage{booktabs}
- \usepackage{sectsty} \subsectionfont{\centering}
- \usepackage{sectsty} \sectionfont{\centering}
- \usepackage{float{
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(grid)
library(png)
library(dplyr)
```
```{r echo=FALSE, results='asis'}
cat(params$n)
cat(params$d)
```
```{r echo=FALSE}
sampleMetrics <- data.frame(
Sample = c("Threshold","A","2","4","11","C","DEF"),
Length = c(">= 6", 10, 11, 11, 11, 11, 12),
Experiment1 = c(">= 10000",5696,8006,6675,9477,5028,7093),
Experiment2 = c(">= 10000", 21223, 27890, 34623, 24152, 25716, 45187),
Sum = c(">=20000", 28409, 41895, 46181, 34129, 12244, 51910),
Total1 = c("N/A", 41382, 132670, 78271, 89930, 98788, 13015),
Total2 = c("N/A", 43170, 53280, 57568, 46584, 51156, 55045),
stringsAsFactors = FALSE
)
super_cell_spec <- function(data, threshold) {
cell_spec(as.numeric(data), "latex", background = ifelse(
as.numeric(data) >= threshold, "#45ff41", "#ff4242"))
}
sampleMetrics$Length[-1] <- super_cell_spec(sampleMetrics$Length[-1], 6)
sampleMetrics$Experiment1[-1] <- super_cell_spec(
sampleMetrics$Experiment1[-1], 10000)
sampleMetrics$Experiment2[-1] <- super_cell_spec(
sampleMetrics$Experiment2[-1], 10000)
sampleMetrics$Sum[-1] <- super_cell_spec(sampleMetrics$Sum[-1], 20000)
sampleMetrics[1,] <- cell_spec(sampleMetrics[1,], "latex",
background = "#afafaf")
sampleMetrics%>%
kable("latex", booktabs = F, escape = F,
col.names = linebreak(c("Sample",
"Length", "Experiment 1",
"Experiment 2","Sum",
"Total\n1", "Total\n2"),
align = "c")) %>%
kable_styling(latex_options = "scale_down")
```
I definitely wouldn't be as confused if it didn't work flawlessly the first time around. Maybe something to do with the envir = new.env(parent = globalenv()) in app.R? Thanks for any thoughts.

Managed to fix this by adding additional packages, mostly through the trial and error of ! Undefined control sequence errors. It would report an issue with multirow and I would look up the right latex package to include.
In the end, my YAML Rmarkdown header looked like:
---
output: pdf_document
always_allow_html: yes
params:
d: NA
st: NA
header-includes:
- \usepackage[table]{xcolor}
- \usepackage{makecell, tabularx, float, multirow, pgfplots}
- \usepackage{booktabs}
- \usepackage{sectsty} \subsectionfont{\centering}
- \usepackage{sectsty} \sectionfont{\centering}
---
This fixed the problem.

Related

Adding image to flextable to be generated with knitr fails but works in RMarkdown chunk

Running R4.1.2 and Windows 10:
I'm trying to knit a document that has a flextable with a ggplot image that was created via ggsave. When I run the code chunk in RMarkdown, it works fine, but when I attempt to knit a word document, I get the following error. If I don't include the image, knitr works fine.
Quitting from lines 350-376 (RPOPS_Draft_Test2.0.Rmd)
Error in read_xml.raw(charToRaw(enc2utf8(x)), "UTF-8", ..., as_html = as_html, :
xmlParseEntityRef: no name [68]
Calls: <Anonymous> ... as_xml_document -> as_xml_document.character -> read_xml.raw
Execution halted
Below are the yaml headers. I am using officedown, as I know this package is required to have images in flextables be rendered in Word.
---
title: "something: `r params$program`"
output:
officedown::rdocx_document:
reference_docx: P:/Reference_doc
params:
program: "something"
---
And here is the code chunk causing the issue.
```{r overall1_flextable}
# chart creation
plot_overall1 <- f_overall_cht(overall_chart1)
plot_overall1_img_out <- ggsave(filename = "plotoverall1img.png", plot = plot_overall1, width = 3.05, height = 0.37, dpi = 600, device = "png")
plot_overall1_in <- file.path(getwd(), "plotoverall1img.png")
example_tibble <- tibble(
col_name = "chart to the right",
chart = ""
)
ft <- flextable(example_tibble)
ft <- compose(ft, i=1, j=2,
value = as_paragraph(
as_image(src = plot_overall1_in, width = 3.05, height = 0.37),
as_chunk(chart)),
part = "body"
)
autofit(ft)
```
I haven't been able to find much on this issue, so any help would be appreciated.
I could not reproduce your error. Below the code to produce your table. There are two solutions, my recommended solution (documented here: https://ardata-fr.github.io/flextable-book/cell-content-1.html#base-plots-and-ggplot-objects) and something closer to what you wrote.
---
title: "test"
output: officedown::rdocx_document
---
```{r setup, include=FALSE}
library(officedown)
library(officer)
library(flextable)
library(ggplot2)
library(tibble)
# chart creation
plot_overall1 <- ggplot(iris, aes(Sepal.Length, Petal.Length)) +
geom_point()+
theme_void()
```
## Recommanded
The solution below is corresponding to the recommanded way.
```{r}
example_tibble <- tibble(
col_name = "chart to the right",
chart = list(plot_overall1)
)
ft <- flextable(example_tibble)
ft <- compose(ft,
j = "chart",
value = as_paragraph(
gg_chunk(value = chart, width = 3.05, height = 0.37, unit = "in")
),
part = "body"
)
autofit(ft)
```
## From scratch
The solution below is corresponding to the way you tried.
```{r}
png_file <- tempfile(fileext = ".png")
plot_overall1_img_out <- ggsave(
filename = png_file,
plot = plot_overall1,
width = 3.05, height = 0.37,
dpi = 600, device = "png")
example_tibble <- tibble(
col_name = "chart to the right"
)
ft <- flextable(example_tibble,
col_keys = c("col_name", "chart"))
ft <- compose(ft,
i = 1, j = "chart",
value = as_paragraph(
as_image(src = png_file, width = 3.05, height = 0.37, unit = "in")
),
part = "body"
)
autofit(ft)
```

Table rendering in pdf document using R markdown

After days trying to find a solution, I give up and ask for help.
I decided to use R Markdown very recently. While I can render plots as I want, I cannot succeed in rendering my tables in a pdf doc properly.
Here the corresponding [EDITED]code:
---
title: "My_title"
output:
pdf_document: default
html_document:
df_print: paged
params:
date: "!r Sys.Date()"
---
```{r library, echo=F, message=F, warning=F, paged.print=FALSE}
suppressMessages(library("knitr"))
suppressMessages(library(reshape2))
suppressMessages(library(splines))
suppressMessages(library(kableExtra))
suppressMessages(library(gplots))
```
```{r, setup, echo = F}
opts_knit$set(root.dir = "my_path")
knitr::opts_chunk$set(echo = F)
```
```{r}
dt <- expand.grid(Region=c("a","b","c"), Country=c("d","e","f"), Cancer= c("All", "CRC", "Breast"),
age.1.1=1:2,
age.1.2=1:2,
age.1.3=1:2)
```
```{r Table_1, INCLUDE = TRUE}
cancer.lab <- c("All", "CRC", "Breast")
for (i in 1:3){
b <- dt[dt$Cancer==cancer.lab[i],]
b <- b[,-3]
t <- kable(b, format = ,caption = "Fig", row.names = F) %>%
kable_paper() %>%
kable_styling(font_size = 9) %>%
add_header_above(c(" " = 2, "1998" = 3))
print(t)
}
```
Again I am new and I surely miss something.
I use Mac if it may explain something.
Thank you for your help.
Sophie.
I think this is the same issue as dealt with here: https://stackoverflow.com/a/53632154/2554330. The problem is that you need to use knit_print to print the tables, but you can't do that in a loop.
So if you change the last code chunk to this, it should work:
```{r Table_1, INCLUDE = TRUE}
results <- c()
cancer.lab <- c("All", "CRC", "Breast")
for (i in 1:3){
b <- dt[dt$Cancer==cancer.lab[i],]
b <- b[,-3]
t <- kable(b, format = ,caption = "Fig", row.names = F) %>%
kable_paper() %>%
kable_styling(font_size = 9) %>%
add_header_above(c(" " = 2, "1998" = 3))
results <- c(results, knit_print(t))
}
asis_output(results)
```

Programmatically create a question_text with multiple answers in r learnr:tutorial

I have the following code with 4 correct answers. I want the students to input all 4 of them. Instead of defining 24 permutations of the answers, I want 4 field boxes that would only accept an answer once.
question_text(
"Input all paths:",
answer("ABEF", correct = TRUE),
answer("ABCDG", correct = TRUE),
answer("ABCDEF",correct = TRUE),
answer("ABDEF", correct = TRUE),
incorrect = "Direction from top to bottom of the plate",
allow_retry = TRUE,
trim = TRUE
)
EDIT
I tried this approach but I do not think I can set the answer as anything other than a single text:
library(gtools)
pat <- permutations(4, 4, c("ABEF","ABCDG","ABCDEF","ABDEF"))
question_text(
"Input all possible rupture paths:",
answer(pat, correct = TRUE),
allow_retry = TRUE,
trim = TRUE
)
Even if I set pat <- c("ABEF","ABCDG","ABCDEF","ABDEF") it does not run successfully. How can define multiple answers at the same time without writing them out.
I'm not sure about your desired output - however, please check the following.
Referring to:
How can define multiple answers at the same time without writing them
out.
You can use lapply to create the answers and do.call to pass the different arguments to question_text:
library(learnr)
do.call(question_text, c(
list("Input all paths:"),
lapply(c("ABEF", "ABCDG", "ABCDEF", "ABDEF"), answer, correct = TRUE),
list(
incorrect = "Direction from top to bottom of the plate",
allow_retry = TRUE,
trim = TRUE
)
))
as *.Rmd file:
---
title: "Tutorial"
output: learnr::tutorial
runtime: shiny_prerendered
---
```{r setup, include=FALSE}
library(learnr)
knitr::opts_chunk$set(echo = FALSE)
```
```{r two-plus-two, exercise=FALSE}
do.call(question_text, c(
list("Input all paths:"),
lapply(c("ABEF", "ABCDG", "ABCDEF", "ABDEF"), answer, correct = TRUE),
list(
incorrect = "Direction from top to bottom of the plate",
allow_retry = TRUE,
trim = TRUE
)
))
```
Regarding:
I want 4 field boxes that would only accept an answer once
Edit: Added an event handler to access to the answers provided by the user.
---
title: "Tutorial"
output: learnr::tutorial
runtime: shiny_prerendered
---
```{r setup, include=FALSE}
library(learnr)
knitr::opts_chunk$set(echo = FALSE)
questions <-
mapply(
FUN = question_text,
lapply(c("ABEF", "ABCDG", "ABCDEF", "ABDEF"), answer, correct = TRUE),
text = paste("Question", 1:4),
incorrect = paste("Incorrect", 1:4),
MoreArgs = list(allow_retry = TRUE,
trim = TRUE),
SIMPLIFY = FALSE
)
```
```{r q1, echo = FALSE}
do.call(quiz, c(list(caption = "Quiz 1"), questions))
```
```{r context="server-start"}
event_register_handler("question_submission", function(session, event, data) {
# names(data):
# "label" "question" "answer" "correct"
message("event: question_submission: ", data$answer)
})
```

Adding background image to R Markdown (.rmd) file for PDF document?

I have seen this post to include a background image to an R markdown report.
I have created a Shiny app to generate a pdf report:
shinyApp(
ui = fluidPage(
sliderInput("slider", "Slider", 1, 10, 5),
downloadButton("report", "Generate report")
),
server = function(input, output) {
test1 <- reactive({
n = input$slider
df=matrix(1:n^2,n,n)
df = as.data.frame(df)
result <- list(df=df,n=n)
return(result)
})
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.pdf",
content = function(file) {
# Copy the report file to a temporary directory before processing it, in
# case we don't have write permissions to the current working dir (which
# can happen when deployed).
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(n = test1()$n,
df = test1()$df)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
And here is my .rmd file :
---
title: "Title"
author: "Name"
date: "`r Sys.Date()`"
output:
pdf_document :
fig_caption: yes
keep_tex: yes
number_sections: yes
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{background}
\backgroundsetup{
scale=1,
color=black,
opacity=0.4,
angle=0,
pages=all,
contents={
\includegraphics[width=\paperwidth,height=\paperheight]{C:/Users/path_to_image/image.jpg}
}
}
params:
n: NA
df: NA
---
```{r}
# The `params` object is available in the document.
params$n
```
A plot of `params$n` random points.
```{r}
plot(rnorm(params$n), rnorm(params$n))
```
```{r}
params$df %>%
mutate_if(is.numeric, function(x) {
cell_spec(x, "latex", bold = T, color = spec_color(x, end = 0.85),
font_size = spec_font_size(x))
}) %>%
kable("latex", escape = F, booktabs = T, linesep = "", align = "c")%>%
kable_styling(latex_options = c("striped", "scale_down"))
```
The error that I'm getting is :
! Undefined control sequence.
l.171 \centering\rowcolors
{2}{gray!6}{white}
Here is how much of TeX's memory you used:
24161 strings out of 492990
415742 string characters out of 6136334
504502 words of memory out of 5000000
27291 multiletter control sequences out of 15000+600000
19644 words of font info for 30 fonts, out of 8000000 for 9000
1141 hyphenation exceptions out of 8191
62i,4n,56p,577b,315s stack positions out of 5000i,500n,10000p,200000b,80000s
[1]: http
Which in tex community they referring to forgetting something like \end{document}. I should mention that if I use the .rmd file alone and replace the last part with :
{r}
library(kableExtra)
library(dplyr)
iris[1:10, ] %>%
mutate_if(is.numeric, function(x) {
cell_spec(x, "latex", bold = T, color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
}) %>%
mutate(Species = cell_spec(
Species, "latex", color = "white", bold = T,
background = spec_color(1:10, end = 0.9, option = "A", direction = -1)
)) %>%
kable("latex", escape = F, booktabs = T, linesep = "", align = "c")
I will be able to compile it with that background image, the current shiny app is also generating the report if I exclude the part that related to the background image setting.
That's because xcolor must be loaded before background. Do:
---
title: "Title"
author: "Name"
date: "`r Sys.Date()`"
output:
pdf_document :
fig_caption: yes
keep_tex: yes
number_sections: yes
header-includes:
\usepackage{background}
\usepackage{float}
\backgroundsetup{
scale=1,
color=black,
opacity=0.4,
angle=0,
pages=all,
contents={
\includegraphics[width=\paperwidth,height=\paperheight]{C:/Users/path_to_image/image.jpg}
}
}
---
Note that your "header-includes" is useless because all these packages are automatically included.

R kableExtra latex: Add linebreaks to rotated header row

I'm trying to produce table to a Latex-pdf document. I'm using kableExtra and knitr in R.
I have a table that has long column names. When I rotate the header row by 90 degrees linebreaks won't work. Does anyone have an idea how I could achieve both rotated row and linebreaks?
My example is the same as in Hao's Best Practice for newline in Latex table, but I added piped row_spec to the end of the code.
\documentclass[10pt,a4paper]{article}
\usepackage[table]{xcolor}
\begin{document}
\begin{table}
<<global_options, echo=FALSE>>=
library(kableExtra)
library("dplyr")
dt_lb <- data.frame(
Item = c("Hello\nWorld", "This\nis a cat"),
Value = c(10, 100)
)
dt_lb %>%
mutate_all(linebreak) %>%
kable("latex", booktabs = T, escape = F,
col.names = linebreak(c("Item\n(Name)", "Value\n(Number)"))) %>%
row_spec(0, angle = 90, align='l', monospace=T)
#
\end{table}
\end{document}
What I get is this, but the [l] tags hint that there's something else wrong with the tags as well:
On StackExchange TEX I found a question about rotation and linebreaks, this is what I'm trying achieve: https://tex.stackexchange.com/questions/14730/big-table-with-rotated-column-labels-using-booktabs
You could use tableHTML:
library(tableHTML)
Replace the new line character "\n" with the HTML tag <br>:
headers <- c("Item\n(Name)", "Value\n(Number)") %>%
stringr::str_replace_all(pattern = "\\n", replacement = "<br>")
Create a tableHTML object and rotate the headers using add_css_header():
dt_lb %>%
tableHTML(rownames = FALSE,
headers = headers,
escape = FALSE,
widths = c(100, 100),
theme = 'scientific') %>%
add_css_header(css = list(c('transform', 'height', 'text-align'),
c('rotate(-45deg)', '70px', 'center')),
headers = 1:2)
The result looks like this:
Note: you can add more css or default themes. Check out the vignettes for more details:
If you want to create a pdf document, you could use RMarkdown:
---
title: "tableHTML2pdf"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
\
```{r}
library(tableHTML)
dt_lb <- data.frame(
Item = c("Hello\nWorld", "This\nis a cat"),
Value = c(10, 100)
)
headers <- c("Item\n(Name)", "Value\n(Number)") %>%
stringr::str_replace_all(pattern = "\\n", replacement = "<br>")
dt_lb %>%
tableHTML(rownames = FALSE,
headers = headers,
escape = FALSE,
widths = c(100, 100),
theme = 'scientific') %>%
add_css_header(css = list(c('transform', 'height', 'text-align'),
c('rotate(-45deg)', '70px', 'center')),
headers = 1:2)
```
\
It will then create an HTML file. This file can then be converted to PDF using wkhtmltopdf.
I think you probably rendered your rmarkdown document into HTML... In the rmarkdown yaml header, does it say html_document right now? If so, you can try to change it to pdf_document.....
I rendered a pdf_document with exactly the same code and I think I got what you were looking for...
---
title: "Table Sample"
output: pdf_document
---
``` {r, include = FALSE}
library(tidyverse)
library(kableExtra)
```
```{r}
dt_lb <- data.frame(
Item = c("Hello\nWorld", "This\nis a cat"),
Value = c(10, 100)
)
dt_lb %>%
mutate_all(linebreak) %>%
kable("latex", booktabs = T, escape = F,
col.names = linebreak(c("Item\n(Name)", "Value\n(Number)"), align = "c")) %>%
row_spec(0, angle = 90)
```
Latex package makecell was missing.
Hao pointed out that Page 3 of this manual lists some of the necessary Latex packages: haozhu233.github.io/kableExtra/awesome_table_in_pdf.pdf

Resources