A script that has been running seamlessly for over a month stopped adding my child Latex code into my main document following an upgrade to R 3.0.1. The following snippet used to include the text from the compiled test.rnw file in my main document (so that it could be compiled as one document). Now it just includes the filenames of the compiled rnw files.
<<run-all, include=FALSE>>=
out = NULL
for (i in 1:10) {
out = c(out, knit_child('test.rnw', sprintf('test-template-%d.tex', i)))
}
#
\Sexpr{paste(out, collapse = '\n')}
When I try to run the knit_child command interactively, I get this error:
> knit_child('test.rnw', sprintf('test-template-%d.tex', i))
Error in setwd(opts_knit$get("output.dir")) : character argument expected
Running knit() alone will compile the Latex code, if I then run knin_child() there is not error but the "out" object just contains the filename of the child file instead of the contents.
Any ideas how to fix this?
You are not supposed to use knit_child() interactively. It was designed to be called inside knit().
As you have noted, knit_child() in the latest version of knitr returns the content of the child document if you do not provide the second argument. By explicitly providing the second argument sprintf('test-template-%d.tex', i), you mean "please write the output to this file and return the filename".
To fix the problem, you need to remove the second argument:
<<run-all, include=FALSE>>=
out = NULL
for (i in 1:10) {
out = c(out, knit_child('test.rnw'))
}
#
\Sexpr{paste(out, collapse = '\n')}
Related
I'm attempting to make my code more modular: data loading and cleaning in one script, analysis in another, etc. If I were using R scripts, this would be a simple matter of calling source on data_setup.R inside analysis.R, but I'd like to document the decisions I'm making in an Rmarkdown document for both data setup and analysis. So I'm trying to write some sort of source_rmd function that will allow me to source the code from data_setup.Rmd into analysis.Rmd.
What I've tried so far:
The answer to How to source R Markdown file like `source('myfile.r')`? doesn't work if there are any repeated chunk names (a problem since the chunk named setup has special behavior in Rstudio's notebook handling). How to combine two RMarkdown (.Rmd) files into a single output? wants to combine entire documents, not just the code from one, and also requires unique chunk names. I've tried using knit_expand as recommended in Generate Dynamic R Markdown Blocks, but I have to name chunks with variables in double curly-braces, and I'd really like a way to make this easy for my colaborators to use as well. And using knit_child as recommended in How to nest knit calls to fix duplicate chunk label errors? still gives me duplicate label errors.
After some further searching, I've found a solution. There is a package option in knitr that can be set to change the behavior for handling duplicate chunks, appending a number after their label rather than failing with an error. See https://github.com/yihui/knitr/issues/957.
To set this option, use options(knitr.duplicate.label = 'allow').
For the sake of completeness, the full code for the function I've written is
source_rmd <- function(file, local = FALSE, ...){
options(knitr.duplicate.label = 'allow')
tempR <- tempfile(tmpdir = ".", fileext = ".R")
on.exit(unlink(tempR))
knitr::purl(file, output=tempR, quiet = TRUE)
envir <- globalenv()
source(tempR, local = envir, ...)
}
I teach a lab and I have my students write their answers in .Rmd files. For grading, I download and render them as pdfs in a batch. I use the following script to render everything and save in a file.
library(rmarkdown)
# Handy functions for concatenating strings because I want to do it like a Python
# programmer damnit!
`%s%` <- function(x,y) {paste(x,y)}
`%s0%` <- function(x,y) {paste0(x,y)}
# You should set the working directory to the one where the assignments are
# located. Also, make sure ONLY .rmd files are there; anything else may cause
# a problem.
subs <- list.files(getwd()) # Get list of files in working directory
errorfiles <- c() # A vector for names of files that produced errors
for (f in subs) {
print(f)
tryCatch({
# Try to turn the document into a PDF file and save in a pdfs subdirectory
# (you don't need to make the subdirectory; it will be created automatically
# if it does not exist).
render(f, pdf_document(), output_dir = getwd() %s0% "/pdfs")
},
# If an error happens, complain, then save the name in errorfiles
error = function(c) {
warning("File" %s% "did not render!")
warning(c)
errorfiles <- c(errorfiles, f)
})
}
This last assignment I forgot to set error=TRUE in the chunks, so documents will fail to compile if errors are found and I will have to go hunt those errors down and fix them. I tried to modify this code so that I set the parameter error=TRUE as default outside the document. Unfortunately, I've been working at this for hours and have found no way to do so.
How can I change this code so I can change this parameter outside the documents? (Bear in mind that I don't own the computer so I cannot install anything, but the packages knitr and rmarkdown are installed.)
Is there a way to test-out and peek at the output of a selected portion of markdown in RStudio? It seems you either run R code or have to compile the entire RMD page in order to see the output.
This is a Windows-only solution and it uses the clipboard instead of the current selection:
Define the following function:
preview <- function() {
output <- tempfile(fileext = ".html")
input <- tempfile(fileext = ".Rmd")
writeLines(text = readClipboard(), con = input)
rmarkdown::render(input = input, output_file = output)
rstudioapi::viewer(output)
}
Then, copy the markdown you want to preview and run preview(). Note that the output might be different from the output in the final document because
the code is evaluated in the current environment
only the copied markdown is evaluated, meaning that the snippet has no context whatsoever.
A solution without using the clipboard will most likely employ rstudioapi::getActiveDocumentContext(). It boils down to something along the lines of a modified preview function
preview2 <- function() {
code <- rstudioapi::getActiveDocumentContext()$selection
# drop first line
# compile document (as in preview())
# stop execution (THIS is the problem)
}
which could be used by running preview() followed by the markdown to render:
preview2()
The value of pi is `r pi`.
The problem is, I don't see how the execution could be halted after calling preview2() to prevent R from trying to parse The value of …. See this related discussion.
I'm using knit2pdf("book.Rnw", quiet=TRUE) to compile a book project under
RStudio. The knit step takes a long time (I'm not yet using caching), and when
there are new references, figures, cross-references, etc. it takes several
passes to resolve them, even if the .Rnw files haven't changed.
What I'd like is an equivalent or extension of knit2pdf which allows
either knit=FALSE to suppress the regeneration of the .tex file, or
an option latex.passes= to request additional runs of tools::texi2pdf.
I've looked at the code in knit2pdf, and it is a bit too opaque to allow
a simple patch for this functionality.
All knit2pdf does is generate a .tex file and then call tools:texi2pdf. If you're looking for a version of knit2pdf that doesn't generate a .tex file first, it is exactly tools::texi2pdf.
Using stringr::str_replace, I do something like this and have found it sufficient:
knit2pdf_mod <- function(rnw_file) {
knit2pdf(rnw_file, compiler = "xelatex")
texi2pdf(file = str_replace(rnw_file, pattern = "Rnw", replacement = "tex"))
}
You could throw in a for loop to repeat the texi2pdf step as many times as you want.
knit2pdf_mod <- function(rnw_file, latex.passes = 1) {
knit2pdf(rnw_file, compiler = "xelatex")
for (i in 1:latex.passes) {
texi2pdf(file = str_replace(rnw_file, pattern = "Rnw", replacement = "tex"))
}
}
Using pure dot inside a knitr chunk with engine = "dot" is straightforward, but you have to write the dot code yourself.
<<r dot-ex, engine = "dot", echo=FALSE>>=
digraph test123 {
A -> B
}
#
I want a function to do it for me.
dotFun <- function() {
dotCode <- 'digraph test123 {
A -> B
}'
return(dotCode)
}
and then call this inside a knit chunk similar to a function that returns LaTeX code and knit with result = 'as.is'
<<r dot-ex, engine = "dot">>=
cat(dotFun())
#
but this results in :Error in (knit_engines$get(options$engine))(options):
setting chunk option results = 'asis' yields the same error message.
Is there a way to do this?
It is not possible with the current version of knitr (v1.5), but will be possible in the next version (v1.6), which has not been released yet. If you use the development version on Github, you can actually assign the source code to a code chunk via the code option, e.g.
<<dot-ex, engine = "dot", code = dotFun()>>=
#
More on this in the news for v1.6.
Any particular reason this has to be evaluated within a knitr chunk with that engine? Why not do it directly from R with some system calls? You can write the command to a file, and use system to call dot on that file, and read the results back into R.
This is, in fact, what knitr does. You can probably pretty easily take the knitr dot engine and wrap it into a function of your own -- see
https://github.com/yihui/knitr/blob/master/R/engine.R#L144.