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.
Related
I have an extensive R script that ranks stocks across 3 indices. I was able to automate it to run for each index and generate a Knitr HTML doc. I have 1 case where the script returns a value (using SVDialogs) and takes in an excel document to finish running. When I add in this case it complicates things since I can't run SVDialogs in RMarkdown.
Any tips on how to overcome this and take in user input while generating an HTML output?
indices <- c("TSX", "TSX Small Cap", "S&P 500")
latestdate <- as.Date('2019-01-17')
renderReport <- function(index, latestdate) {
rmarkdown::render("test.Rmd",
output_file = paste0(index," Score",".html"),
params=list(index=index,
latestdate=latestdate),
output_options = list(self_contained = FALSE, lib_dir = "libs"))
}
purrr::walk2(indices,latestdate, renderReport)
I had to redesign my code to be run from the script instead of markdown then use rmarkdown::render() to create the file. This still allows for user input.
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 have a shiny app that allows the user to download an HTML file (knitted from a .Rmd file) that includes the code used to run the analysis based on all the user inputs. I am trying to write the base .Rmd file that gets altered when user inputs vary. I am having trouble including user input variables (e.g. input$button1) into R code chunks. Say the user input for input$button1 = "text1".
```{r}
results <- someFun(input$button1)
```
And I'd like to have it knitted like this:
```{r}
results <- someFun('text1')
```
Every time I download the knitted HTML though, I get input$button1 getting written to file. I would also like to be able to produce an .Rmd file that is formatted with this substitution. It seems like knit_expand() might be the key, but I can't seem to relate available examples to my specific problem. Is the proper way to knit_expand() the whole .Rmd file and specify explicitly all the parameters you want subbed in, or is there a more elegant way within the .Rmd file itself? I would prefer a method similar to this, except that instead of using the asis engine, I could use the r one. Any help would be greatly appreciated. Thanks!
Got it. Solution below. Thanks to Yihui for the guidance. The trick was to knit_expand() the whole .Rmd file, then writeLines() to a new one, then render. With hindsight, the whole process makes sense. With hindsight.
For the example, p1 is a character param 'ice cream' and p2 is an integer param 10. There is a user-defined param in ui.R called input$mdType that is used to decide on the format provided for download.
Rmd file:
Some other text.
```{r}
results <- someFun("{{p1}}", {{p2}})
```
in the downloadHandler() within server.R:
content = function(file) {
src <- normalizePath('userReport.Rmd')
# temporarily switch to the temp dir, in case you do not have write
# permission to the current working directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'userReport.Rmd')
exp <- knit_expand('userReport.Rmd', p1=input$p1, p2=input$p2)
writeLines(exp, 'userReport2.Rmd')
out <- rmarkdown::render('userReport2.Rmd', switch(input$mdType,
PDF = pdf_document(), HTML = html_document(), Word = word_document()))
}
file.rename(out, file)
}
Resulting userReport2.Rmd before rendering:
```{r}
results <- someFun("ice cream", 10)
```
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.
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')}