Error handling within Sexpr - r

How do I permit errors within \Sexpr?
I have a knitr document. A small part of this document refers to a file that cannot be shared. So whenever \Sexpr{a} is called on for some object a that depends on that file being read, it returns an error. I'd like instead for \Sexpr to print that it encountered an error.
For example,
\documentclass{article}
\usepackage{xcolor} % for red
\begin{document}
<<>>=
x <- 1
#
The value of $x$ is \Sexpr{x}
<<>>=
a <- scan("secret_file.txt")
#
The value of $a$ is \Sexpr{a}.
\end{document}
will not compile (when secret_file.txt isn't present). I'd like the output to look something like:
I thought that altering the inline hook would work, but putting the following chunk made no difference.
<<Sexpr-setup>>=
library(knitr)
knit_hooks$set(inline = function(x){
out <- tryCatch(
{
if (is.numeric(x))
x = round(x, getOption("digits"))
paste(as.character(x), collapse = ", ")
},
error = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr error!}}")
invisible(NULL)
},
warning = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr warning!}}")
invisible(NULL)
}
)
return(out)
})
#
It is not essential to have a custom error message, only that errors are clear from the output and do not prevent compilation. I appreciate that I could do a find replace into something like \Sexpr{XX( and define a function upfront XX() that does the same tryCatch maneouvre, but I thought knitr could do this.
Calling knitr::knit on the above and applying the traceback shows that:
11: eval(expr, envir, enclos)
10: eval(parse_only(code[i]), envir = envir)
9: withVisible(eval(parse_only(code[i]), envir = envir))
8: inline_exec(block)
7: in_dir(opts_knit$get("root.dir") %n% input_dir(), inline_exec(block))
6: call_inline(x)
5: process_group.inline(group)
4: process_group(group)
3: withCallingHandlers(if (tangle) process_tangle(group) else process_group(group),
error = function(e) {
setwd(wd)
cat(res, sep = "\n", file = output %n% "")
message("Quitting from lines ", paste(current_lines(i),
collapse = "-"), " (", knit_concord$get("infile"),
") ")
})
2: process_file(text, output)
1: knitr::knit("knitr-prevent-errors.Rnw", quiet = TRUE)
From following the functions, it appears that the error is low down at
eval(parse_only(code[i]), envir = envir)
Where code[i] is a. Am I right in thinking that the only way to resolve this is to change the line starting v = with a tryCatch?

With the option include=FALSE in the setup chunk,the following worked for me with output as below. If it does not work for you I will delete the post
\documentclass{article}
\usepackage{xcolor} % for red
<<setup, include=FALSE>>=
knit_hooks$set(inline = function(x) {
out <- tryCatch(
{
if (is.numeric(x))
x = round(x, getOption("digits"))
paste(as.character(x), collapse = ", ")
},
error = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr error!}}")
invisible(NULL)
},
warning = function(cond){
return("\\textcolor{red}{\\textbf{Sexpr warning!}}")
invisible(NULL)
}
)
return(out)
})
#
\begin{document}
<<>>=
x <- 1
#
The value of $x$ is \Sexpr{x}
<<>>=
a <- scan("secret_file.txt")
#
The value of $a$ is \Sexpr{a}.
\end{document}
Knitr Output:
>knitr::knit("test.Rnw")
processing file: test.Rnw
|......... | 14%
ordinary text without R code
|................... | 29%
label: setup (with options)
List of 2
$ include: logi FALSE
$ indent : chr " "
|............................ | 43%
ordinary text without R code
|..................................... | 57%
label: unnamed-chunk-1 (with options)
List of 1
$ indent: chr " "
|.............................................. | 71%
inline R code fragments
|........................................................ | 86%
label: unnamed-chunk-2 (with options)
List of 1
$ indent: chr " "
|.................................................................| 100%
inline R code fragments
output file: test.tex
[1] "test.tex"
Tex Output:
>texi2pdf("test.tex")
>
I am using MikTex 2.9,knitr 1.9, R 3.0.2 on Windows , can you please attach your log files then we can compare the differences if any

Related

Compile quarto document in temporary directory in R

I want to compile a template quarto report in a temporary directory. In the real case, the template is in an R package, and therefore has to compiled in a temporary directory. But I get the following error:
# This will create a file named "template.qmd" in the current folder.
# Used in: the "template.qmd" is a parametrized report and in a package. The report
# will be compiled in a temporary directly which will be cleaned afterwards.
f <- c("---", "title: \"Test\"", "format: html", "---", "", "## Set a variable",
"", "```{r}", "OK <- FALSE", "```", "", "## Running Code depending on value of `OK`",
"", "```{r}", "#| eval: !expr OK", "print(\"OK is TRUE - otherwise you won't see anything here.\")",
"```", "")
writeLines(f, "template.qmd")
name <- "Test_Report"
output_format <- "html"
output_file <- paste0(name, ".html")
tmpdir <- tempfile()
dir.create(tmpdir)
template <- file.path(tmpdir, "template.qmd")
file.copy(
file.path(".", "template.qmd"),
template
)
report <- quarto::quarto_render(
input = template,
output_format = output_format,
output_file = output_file
)
# Here the error occurs:
#
# processing file: template.qmd
# |.............. | 20%
# ordinary text without R code
#
# |............................ | 40%
# label: unnamed-chunk-1
# |.......................................... | 60%
# ordinary text without R code
#
# |........................................................ | 80%
# label: unnamed-chunk-2 (with options)
# List of 1
# $ eval: logi FALSE
#
# |......................................................................| 100%
# ordinary text without R code
#
#
# output file: template.knit.md
#
# pandoc --output ../../../../../../../Users/rainerkrug/tmp/test/Test_Report.html
# to: html
# standalone: true
# section-divs: true
# html-math-method: mathjax
# wrap: none
# default-image-extension: png
#
# metadata
# document-css: false
# link-citations: true
# date-format: long
# lang: en
# title: Test
#
# pandoc: ../../../../../../../Users/rainerkrug/tmp/test/Test_Report.html: openFile: does not exist (No such file or directory)
# Error in `processx::run(quarto_bin, args, echo = TRUE)`:
# ! System command 'quarto' failed
# ---
# Exit status: 1
# stdout & stderr: <printed>
# ---
# Type .Last.error to see the more details.
# And I would like to continuye as follows:
file.copy(
file.path(tmpdir, output_file),
file.path(".", output_file),
)
unlink(tmpdir)
Session Info:
> sessionInfo()
R version 4.2.2 (2022-10-31)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.1
Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] Rcpp_1.0.9 ps_1.7.2 digest_0.6.31 later_1.3.0 R6_2.5.1
[6] jsonlite_1.8.4 evaluate_0.19 rlang_1.0.6 cli_3.6.0 rstudioapi_0.14
[11] rmarkdown_2.19 tools_4.2.2 yaml_2.3.6 xfun_0.36 fastmap_1.1.0
[16] compiler_4.2.2 processx_3.8.0 htmltools_0.5.4 knitr_1.41 quarto_1.2
>
Is this a bug in quarto, or am I doing something obvious wrong?
There seems to be a bug in quarto / panda on Mac, as it works on Ubuntu. The problem is the argument output_file = output_file. As soon as it is present, the Mac implementation fails. I solved it wit the following:
f <- c("---", "title: \"Test\"", "format: html", "---", "", "## Set a variable",
"", "```{r}", "OK <- FALSE", "```", "", "## Running Code depending on value of `OK`",
"", "```{r}", "#| eval: !expr OK", "print(\"OK is TRUE - otherwise you won't see anything here.\")",
"```", "")
writeLines(f, "template.qmd")
name <- "Test_Report"
output_format <- "html"
output_file <- paste0(name, ".html")
tmpdir <- tempfile()
dir.create(tmpdir)
template <- file.path(tmpdir, paste0(name, ".qmd"))
file.copy(
file.path(".", "template.qmd"),
template
)
report <- quarto::quarto_render(
input = template,
output_format = output_format
)
fn <- c(paste0(name, ".html"), paste0(name, "_files"))
file.copy(
file.path(tmpdir, fn),
file.path("."),
recursive = TRUE
)
unlink(tmpdir)

Chunk option eval=FALSE ignored when spinning R-script

Spinning the following code (by clicking compile report in Rstudio):
#+ eval = FALSE
This line should not be syntax-checked, but it is.
Returns this error:
Error in parse(text = x, keep.source = TRUE) :
<text>:2:6: unexpected symbol
1: #+ eval = FALSE
2: This line
Knitting the equivalent Rmd-chunk works fine:
```{r, eval = FALSE}
Using Rmd, eval=FALSE disables the syntax-check, and does not error
I was expecting that I could spin a chunk syntactically incorrect code without getting an error (https://bookdown.org/yihui/rmarkdown-cookbook/spin.html). Am I mistaken for expecting this?
Thanks.
This is not possible, but a workaround is to quote the sentence :
# Syntax checked:
2+2
#> [1] 4
# Not syntax checked:
"
2 a
"
#> [1] "\n2 a \n"
(source: Yihui Xie's comment above at 28jun2022)

rmarkdown render NSE function fails only inside callr

I seem to have a weird combination of NSE, rmarkdown and callr, similar in flavor to Is it possible to disable `callr` for RMarkdown?.
When I set a value to a variable to use it in something similar to a filter call implemented using NSE via nested evals and list calls, it fails horribly, but only in callr.
---
title: "Test CC2 Failure Reproducibly"
author: "Robert M Flight"
output: rmarkdown::md_document
editor_options:
chunk_output_type: console
---
```{r run_enrichments}
set.seed(1234)
create_go_annotation = function(db, ontology = NULL){
all_genes = keys(db)
go_all_gene = AnnotationDbi::select(db, keys = all_genes, columns = c("GOALL", "ONTOLOGYALL"))
if (!is.null(ontology)) {
go_all_gene = go_all_gene[go_all_gene$ONTOLOGYALL == ontology, ]
ontology_type = paste0("GO.", ontology)
} else {
ontology_type = "GO.all"
}
go_2_gene = split(go_all_gene$ENTREZID, go_all_gene$GOALL)
go_2_gene = lapply(go_2_gene, unique)
go_desc = AnnotationDbi::select(GO.db::GO.db, keys = names(go_2_gene), columns = "TERM", keytype = "GOID")$TERM
names(go_desc) = names(go_2_gene)
go_annotation = categoryCompare2::annotation(annotation_features = go_2_gene,
description = go_desc,
annotation_type = ontology_type,
feature_type = "ENTREZID")
go_annotation
}
library(org.Hs.eg.db)
library(GO.db)
library(categoryCompare2)
library(methods)
go_mf = create_go_annotation(org.Hs.eg.db, "MF")
all_features = unique(unlist(go_mf#annotation_features))
sig_features = sample(all_features, 500)
enrich = hypergeometric_feature_enrichment(
new("hypergeom_features", significant = sig_features,
universe = all_features,
annotation = go_mf),
p_adjust = "BH"
)
comb_enrich = combine_enrichments(sig1 = enrich)
sig_cutoff = 0.1
filter_enrich = get_significant_annotations(comb_enrich, padjust <= sig_cutoff)
```
Run it via callr:
r(function() rmarkdown::render(here::here("categoryCompare2_failure.Rmd"), output_file = "cc2_fails_1.md"), show = TRUE)
# Quitting from lines 13-57 (categoryCompare2_failure.Rmd)
#
# Error in FUN(X[[i]], ...) : object 'sig_cutoff' not found
# Error: callr subprocess failed: object 'sig_cutoff' not found
# > .Last.error.trace
# Stack trace:
# Process 221313:
# 1. callr:::r(function() rmarkdown::render(here::he ...
# 2. callr:::get_result(output = out, options)
# 3. throw(newerr, parent = remerr[[2]])
# x callr subprocess failed: object 'sig_cutoff' not found
# Process 221619:
# 15. (function () ...
# 16. rmarkdown::render(here::here("categoryCompare2_failure.Rmd"))
# 17. knitr::knit(knit_input, knit_output, envir = envir, quiet ...
# 18. knitr:::process_file(text, output)
# 19. base:::withCallingHandlers(if (tangle) process_tangle(gro ...
# 20. knitr:::process_group(group)
# 21. knitr:::process_group.block(group)
# 22. knitr:::call_block(x)
# 23. knitr:::block_exec(params)
# 24. knitr:::eng_r(options)
# 25. knitr:::in_dir(input_dir(), evaluate(code, envir = env, n ...
# 26. knitr:::evaluate(code, envir = env, new_device = FALSE, k ...
# 27. evaluate::evaluate(...)
# 28. evaluate:::evaluate_call(expr, parsed$src[[i]], envir = e ...
# 29. evaluate:::timing_fn(handle(ev <- withCallingHandlers(wit ...
# 30. base:::handle(ev <- withCallingHandlers(withVisible(eval( ...
# 31. base:::withCallingHandlers(withVisible(eval(expr, envir, ...
# 32. base:::withVisible(eval(expr, envir, enclos))
# 33. base:::eval(expr, envir, enclos)
# 34. base:::eval(expr, envir, enclos)
# 35. categoryCompare2:::get_significant_annotations(comb_enric ...
# 36. categoryCompare2:::get_significant_annotations(comb_enric ...
# 37. categoryCompare2:::.get_significant_combined_enrichment(i ...
# 38. base:::lapply(in_results#enriched, function(x) { ...
# 39. categoryCompare2:::FUN(X[[i]], ...)
# 40. categoryCompare2:::get_significant_annotations(x#statisti ...
# 41. categoryCompare2:::get_significant_annotations(x#statisti ...
# 42. categoryCompare2:::.get_significant_stat_results(in_resul ...
# 43. categoryCompare2:::multi_query_list(in_results#statistic_ ...
# 44. base:::lapply(queries, eval, list_to_query)
# 45. base:::FUN(X[[i]], ...)
# 46. base:::FUN(X[[i]], ...)
# 47. base:::.handleSimpleError(function (e) ...
# 48. h(simpleError(msg, call))
# x object 'sig_cutoff' not found
You can see that it complains that sig_cutoff is not found, but it exists in the environment, but does not seem to get passed down.
If I instead run it directly, it works:
rmarkdown::render(here::here("categoryCompare2_failure.Rmd"), output_file = "cc2_works.md")
I've put all the code in a github repo.
Interestingly, it's definitely a callr issue, because targets has the same issue.
callr v 1.0.7, rmarkdown v 2.11, R 4.1.0
Other package versions are in the renv.lock file.

Using R Hmisc summary/summaryM latex command within Knitr Markdown pdf

I have been trying to get the Hmisc latex.summary and latex.summaryM examples to work within a pdf document created using Knitr in RStudio. But keep getting error messages. The example data is:
options(digits=3)
set.seed(173)
sex <- factor(sample(c("m","f"), 500, rep=TRUE))
country <- factor(sample(c('US', 'Canada'), 500, rep=TRUE))
age <- rnorm(500, 50, 5)
sbp <- rnorm(500, 120, 12)
label(sbp) <- 'Systolic BP'
units(sbp) <- "mmHg"
treatment <- factor(sample(c("Drug","Placebo"), 500, rep=TRUE))
sbp[1] <- NA
# Generate a 3-choice variable; each of 3 variables has 5 possible levels
symp <- c('Headache','Stomach Ache','Hangnail',
'Muscle Ache','Depressed')
symptom1 <- sample(symp, 500,TRUE)
symptom2 <- sample(symp, 500,TRUE)
symptom3 <- sample(symp, 500,TRUE)
Symptoms <- mChoice(symptom1, symptom2, symptom3, label='Primary Symptoms')
And I want to create a pdf document that contains the tables
tab1 <- summary(sex ~ treatment + Symptoms, fun=table)
tab2 <- summaryM(age + sex + sbp + Symptoms ~ treatment,
groups='treatment', test=TRUE)
I'm running R version 3.5.2 (2018-12-20), RStudio 1.1.463, Hmisc_4.2-0, and have installed tinytex using tinytex::install_tinytex().
After a few hours trial and error I discovered how, and am posting the code below in case it helps others.
The following code works for me, note;
Requirement for relsize latex package when Hmisc::units attribute is used to prevent the following failed to compile error.
! Undefined control sequence.
<recently read> \smaller
The mylatex function is taken from https://stackoverflow.com/a/31443576/4241780, and is required for removing unwanted output.
The option file = "" is needed to prevent the error
Error in system(comd, intern = TRUE, wait = TRUE) : 'yap' not found
Calls: <Anonymous> ... print -> print.latex -> show.latex -> show.dvi -> system
The use of the where = "!htbp" option ensures that the tables remain where they are placed and do not float to the top of the page (by default where = "!tbp") https://tex.stackexchange.com/a/2282.
---
title: "Untitled"
author: "Author"
date: "15 April 2019"
output:
pdf_document:
extra_dependencies: ["relsize"]
---
```{r setup, include=FALSE}
library(Hmisc)
library(dplyr)
mylatex <- function (...) {
o <- capture.output(latex(file = "", where = "!htbp", ...))
# this will strip /all/ line-only comments; or if you're only
# interested in stripping the first such comment you could
# adjust accordingly
o <- grep('^%', o, inv=T, value=T)
cat(o, sep='\n')
}
```
```{r data}
# As in question above ...
```
Here is the first table
```{r tab1, results = "asis"}
tab1 <- summary(sex ~ treatment + Symptoms, fun=table)
mylatex(tab1)
```
Here is the second table
```{r tab2, results = "asis"}
tab2 <- summaryM(age + sex + sbp + Symptoms ~ treatment, test=TRUE)
mylatex(tab2)
```

knitr doesn't convert xtable output on R 3.0.2

I would like to create a tex table using xtable(). Here's my minimal example which worked when I used the same R version on Win 7.
\documentclass[a4paper,12pt,twoside]{article}
\begin{document}
<<load-packages,include=TRUE,echo=TRUE>>=
library(xtable)
#
<<testing-xtable,echo=TRUE,cache=FALSE,include=TRUE>>=
tab <- matrix(1:50,nrow=10)
rownames(tab) <- letters[1:10]
print(
xtable(
x=tab,
caption="A table",
label="tab",
align=rep("c",times=6),
digits=3,
display=rep("f",times=6)
),
sanitize.colnames.function=identity,
include.rownames=FALSE,
table.placement="h"
)
#
\end{document}
Instead of a nice table I get the verbatim code output of xlatex() in the pdf document.
Here's the output of knitr:
> grDevices::pdf.options(useDingbats = FALSE); require(knitr); opts_knit$set(concordance = TRUE); knit('xtable.Rnw', encoding='UTF-8')
Loading required package: knitr
processing file: xtable.Rnw
|............. | 20%
ordinary text without R code
|.......................... | 40%
label: load-packages (with options)
List of 2
$ include: logi TRUE
$ echo : logi TRUE
|....................................... | 60%
ordinary text without R code
|.................................................... | 80%
label: testing-xtable (with options)
List of 3
$ echo : logi TRUE
$ cache : logi FALSE
$ include: logi TRUE
|.................................................................| 100%
ordinary text without R code
output file: xtable.tex
[1] "xtable.tex"
>
>
Running pdflatex on xtable.tex...completed
Created PDF: ~/Dropbox/intern/sandbox(coding)/tex/chapter/chapter/sandbox/xtable/xtable.pdf
Issues: 2 badboxes
The code chunk testing-xtable should be echoed in the final document but it isn't. This is the pdf output. I'm suspicious about the message Ordinary text without R code. Is this normal?
Any help would be greatly appreciated.
Use the chunk option results='asis'.

Resources