Parameters in Knitr - r

I'm trying to write a Rmarkdown code in which the user interactively inserts an excel table and, then a report is automatically generated. First, in the YAML I've written:
---
title: "Test"
author: "Test"
date: "Test"
output: html_document
params:
data:
label: "Insert your data:"
value: results.csv
input: file
---
Then, in the chunk 1 I've used:
```{r ,warning= FALSE, message=FALSE, echo=FALSE }
library(tidyverse)
rmarkdown::render('Test.Rmd', params = 'ask')
df = as.data.frame(readxl::read_excel(params$data))
```
While running this code aforementioned, the navigator opens with a browser to input the file, and there are two buttons "cancel" and "save" (should it not be 'Knit'?)
When I 'save', the output is: "Error params object already exists in knit environment so can't be overwritten by render params"
Therefore, I've tried:
```{r ,warning= FALSE, message=FALSE, echo=FALSE }
library(tidyverse)
rmarkdown::render('Test.Rmd', params = 'ask', envir = new.env())
df = as.data.frame(readxl::read_excel(params$data))
```
Again, I insert the data file and the output is: Error in parse_block(g[-1], g[1], params.src, markdown_mode) : Duplicate chunk label 'setup', which has been used for the chunk: knitr::opts_chunk$set(echo = TRUE) Calls: ... process_file -> split_file -> lapply -> FUN -> parse_block
I'm not finding the issue and why it is happening. Could someone help me?

Related

Run an R Markdown based on interactive parameter choice

I am trying to do the following on R Markdown. Basically, I would like the user to be able to select between two values of a parameter called "Machine" and based on the value selected run some chunks and not others. I know that the "eval" option might be useful here but I have no clue on how to use it in order to reach my goal.
My code for the moment is this (in R Markdown):
---
title: "SUM and SAM"
output: html_document
params:
machine:
label: "Machine"
value: SUM
input: select
choices: [SUM, SAM]
printcode:
label: "Display Code:"
value: TRUE
date: !r Sys.Date()
data:
label: "Input dataset:"
value: None
input: file
years_of_study:
input: slider
min: 2018
max: 2020
step: 1
round: 1
sep: ''
value: [2018, 2019]
---
```{r setup, include=FALSE}
############# IMPORTANT ###################################
#Remember to Knit with Parameters here using the "Knit button"--> "Knit with Parameters".
####################################################
#If you only want the parameters to be shown, run the following.
#knit_with_parameters('~/Desktop/Papers/git_hub/sum_sam.Rmd')
#This must be left uncommented if we want to show the content of the Markdown file once "Knit with Parameters" is pressed.
knitr::opts_chunk$set(echo = TRUE)
Say now I would like a chunk that will execute only if machine = SAM. How can I do that?
Was thinking about something like:
{r pressure, echo=FALSE, eval=params$machine}
plot(pressure)
but does not work
Thank you,
Federico
Let there be a file called foo.Rmd with this content:
---
title: "SUM and SAM"
output: html_document
params:
machine:
input: select
choices: [SUM, SAM]
value: SUM
---
```{r, eval = params$machine == "SAM", echo=FALSE}
print("SAM was chosen")
```
```{r, eval = params$machine == "SUM", echo=FALSE}
print("SUM was chosen")
```
Then you can do:
rmarkdown::render("foo.Rmd", params = list(machine = "SAM"))
Alternativeley, there is the option knit with parameters in RStudio:
Resulting in foo.html:

Create code snippets by a loop in rmardown

Similar to how to create a loop that includes both a code chunk and text with knitr in R i try to get text and a Code snippet created by a Loop.
Something along this:
---
title: Sample
output: html_document
params:
test_data: list("x <- 2", "x <- 4")
---
for(nr in 1:3){
cat(paste0("## Heading ", nr))
```{r, results='asis', eval = FALSE, echo = TRUE}
params$test_data[[nr]]
```
}
Expected Output would be:
What i tried:
I tried to follow: https://stackoverflow.com/a/36381976/8538074. But printing "```" did not work for me.
You can make use of knitr hooks. Take the following MRE:
---
title: "Untitled"
output: html_document
params:
test_data: c("x <- 2", "x <- 4")
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, results = 'asis', echo = F}
hook <- knitr::hooks_html()$source
opts <- knitr::opts_chunk$get()
chunks <- eval(parse(text = params$test_data))
for(nr in seq_along(chunks)){
cat(paste0("## Heading ", nr, "\n"))
cat(hook(chunks[nr], options = opts))
}
```
We get the default source hook and also the default chunk options. Then we get the test data, which is supplied as a string. Therefore we parse and evaluate that string.
In the loop we simply call the source hook on each element of the test data. Here is the result:

Variables unknown when using rmarkdown::render

When I render an RMD automatically calling rmarkdown::render() within an R-Script, I run into trouble when - within the RMD itself - I try to access list-variables. In the example I want to loop through the content of the list variable and render a table for each list.
The first chunk
# This works
```{r, echo = FALSE, results='show'}
knitr::kable(a[[1]])
```
within the RMD renders successfully. However, the second section chunk
# This doesn't work
```{r, echo = FALSE, results='show'}
for (i in 1:length(a)) {
knitr::kable(a[[i]])
}
doesn't evaluate at all. There is not even an error/warning. The complete output renders as follows:
How can I successfully render the second chunk, named 'This doesn't work'? I'd expect to see 3 lists here, displaying the numbers 1:10, 11:20, 21:30.
Reproducible example: Save the following script as render.R:
setwd("C:/path_to_your_script_location/")
# generate a list containing 3 lists
a <- list(list(tour_id=1:10), list(tour_id=11:20), list(tour_id=21:30))
rmarkdown::render("test.Rmd", output_dir = "./", output_file = "out_test.html",
encoding = "UTF-8", quiet = TRUE)
and save the following content as test.Rmd:
---
title: Test
author: "Author"
date: "May 9th, 2018"
output: html_document
---
# This works
```{r, echo = FALSE, results='show'}
knitr::kable(a[[1]])
```
# This doesn't work
```{r, echo = FALSE, results='show'}
for (i in 1:length(a)) {
knitr::kable(a[[i]])
}
```
My solution: Change your last chunk to
```{r, echo = FALSE, results='asis'}
for (i in 1:length(a)) {
print(knitr::kable(a[[i]]))
}
```

R Markdown Error in inherits(x, "list) object not found

Good Morning!
In an R Markdown chunk, I am trying to use kable to spit out a table in rmarkdown. Here's my dummy data:
whytheerror <- data.frame(name=c('school1','school2','school3','school4','school5','school6','school7','school8','school9','school10','school11'), count=c(13,25,36,44,58,63,76,85,93,78,101), percent=c(.7,.6,.2,.32,.41,.44,.97,.02,.31,.5,.11), other_count=c(15,111,33,74,19,5,3,111,1,37,501), other_percent=c(.4,.6,.3,.39,.45,.5,.02,.4,.06,.64,.11))
Here's my code:
```{r echo = FALSE, results = 'asis'}
kable(whytheerror [1:12, ], caption = "Respondent Breakdown")
```
and the error reads:
Error in inherits(x,"list"): object 'whytheerror ' not found calls: <Anonymous>...withCallingHandlers -> withVisible -> eval -> eval -> kable -> inherits
I'm having difficulty figuring out what this error means much less fixing it. can someone assist with either or both?
thank you
This
---
title: "Test"
output: html_document
---
```{r}
whytheerror <- data.frame(name=c('school1','school2','school3','school4','school5','school6','school7','school8','school9','school10','school11'), count=c(13,25,36,44,58,63,76,85,93,78,101), percent=c(.7,.6,.2,.32,.41,.44,.97,.02,.31,.5,.11), other_count=c(15,111,33,74,19,5,3,111,1,37,501), other_percent=c(.4,.6,.3,.39,.45,.5,.02,.4,.06,.64,.11))
```
```{r echo = FALSE, results = 'asis'}
library(knitr)
kable(whytheerror[1:11, ], caption = "Respondent Breakdown")
```
produces
No error.

purl() within knit() duplicate label error

I am knitting a .Rmd file and want to have two outputs: the html and a purl'ed R script each time I run knit. This can be done with the following Rmd file:
---
title: "Purl MWE"
output: html_document
---
```{r}
## This chunk automatically generates a text .R version of this script when running within knitr.
input = knitr::current_input() # filename of input document
output = paste(tools::file_path_sans_ext(input), 'R', sep = '.')
knitr::purl(input,output,documentation=1,quiet=T)
```
```{r}
x=1
x
```
If you do not name the chunk, it works fine and you get html and .R output each time you run knit() (or click knit in RStudio).
However, if you name the chunk it fails. For example:
title: "Purl MWE"
output: html_document
---
```{r}
## This chunk automatically generates a text .R version of this script when running within knitr.
input = knitr::current_input() # filename of input document
output = paste(tools::file_path_sans_ext(input), 'R', sep = '.')
knitr::purl(input,output,documentation=1,quiet=T)
```
```{r test}
x=1
x
```
It fails with:
Quitting from lines 7-14 (Purl.Rmd)
Error in parse_block(g[-1], g[1], params.src) : duplicate label 'test'
Calls: <Anonymous> ... process_file -> split_file -> lapply -> FUN -> parse_block
Execution halted
If you comment out the purl() call, it will work with the named chunk. So there is something about how the purl() call is also naming chunks which causes knit() to think there are duplicate chunk names even when there are no duplicates.
Is there a way to include a purl() command inside a .Rmd file so both outputs (html and R) are produced? Or is there a better way to do this? My ultimate goal is to use the new rmarkdown::render_site() to build a website that updates the HTML and R output each time the site is compiled.
You can allow duplicate labels by including options(knitr.duplicate.label = 'allow') within the file as follows:
title: "Purl MWE"
output: html_document
---
```{r GlobalOptions}
options(knitr.duplicate.label = 'allow')
```
```{r}
## This chunk automatically generates a text .R version of this script when running within knitr.
input = knitr::current_input() # filename of input document
output = paste(tools::file_path_sans_ext(input), 'R', sep = '.')
knitr::purl(input,output,documentation=1,quiet=T)
```
```{r test}
x=1
x
```
This code isn't documented on the knitr website, but you can keep track with the latest changes direct from Github: https://github.com/yihui/knitr/blob/master/NEWS.md
A related approach to #ruaridhw solution would be to wrap the knitr::purl() in callr::r(). See function below that saves the R chunks from a specified R markdown file to a temporary .R file:
# RMD to local R temp file
# inspiration: https://gist.github.com/noamross/a549ee50e8a4fd68b8b1
rmd_chunks_to_r_temp <- function(file){
temp <- tempfile(fileext=".R")
# needed callr so can use when knitting -- else can bump into "duplicate chunk
# label" errors when running when knitting
callr::r(function(file, temp){
knitr::purl(file, output = temp)
},
args = list(file, temp))
}
This function also exists in funspotr:::rmd_chunks_to_r_temp() at brshallo/funspotr.
You can avoid this error with a bash chunk that calls purl in a separate R session. That way there's no need to allow duplicate labels.
An example use case is an Rmd file where the code is run (and not echo'd) throughout the report and then all the code chunks are shown with chunks names and code comments in an Appendix. If you don't require that additional functionality then you would only need up until the bash chunk.
The idea is that report_end signifies where to stop purl such that the appendix code isn't considered "report code". Then read_chunk reads the entire R file into one code chunk which can then be echo'd with syntax highlighting if required.
---
title: "Purl MWE"
output: html_document
---
These code chunks are used in the background of the report however
their source is not shown until the Appendix.
```{r test1, echo=FALSE}
x <- 1
x
```
```{r test2, echo=FALSE}
x <- x + 1
x
```
```{r test3, echo=FALSE}
x <- x + 1
x
```
# Appendix
```{r, eval=TRUE}
report_end <- "^# Appendix"
temp <- tempfile(fileext = ".R")
Sys.setenv(PURL_IN = shQuote("this_file.Rmd"), # eg. knitr::current_input()
PURL_OUT = shQuote(temp),
PURL_END = shQuote(report_end))
```
```{bash, include=FALSE}
Rscript -e "lines <- readLines($PURL_IN, warn = FALSE)" \
-e "knitr::purl(text = lines[1:grep($PURL_END, lines)], output = $PURL_OUT, documentation = 1L)"
```
```{r, include=FALSE}
knitr::read_chunk(temp, labels = "appendix")
unlink(temp)
```
```{r appendix, eval=FALSE, echo=TRUE}
```

Resources