By default RMarkdown tends to split the output. So that:
```{r, collapse = FALSE}
print(1)
print(2)
```
comes as:
Making collapse = TRUE should remove the breaks in the output but it doesn't. Does anyone know why?
You must use the results = "hold" option to include all text output from the evaluated chunk together in the document.
```{r, results = "hold"}
print(1)
print(2)
```
See the text output options of the knitr package for details.
Related
I'm trying to generate a rmarkdown chunk using code. I've read similar questions and their solutions, such as using pander or using cat. I just can't seem to generate it. I also tried knitting the output manually. Here's an example of a Rmd file:
---
title: "test"
output: pdf_document
---
## R Markdown
```{r, results='asis',echo=FALSE}
txt <- paste("```{r}",
"2+2",
"```")
pander::pander(txt)
```
When I knit this, I get a verbatim {r} 2+2. I would like to see the number four instead. In my real example, I'm using bookdown and trying to generate a block2 chunk.
Any ideas how to generate this chunk that gets evaluated as R code?
Does this do what you want?
## R Markdown
```{r, results='asis',echo=FALSE}
txt <- paste("```{r}",
2+2,
"```")
pander::pander(txt)
```
This evalutates to
```{r} 4 ```
in your markdown document.
You using a string literal "2+2" as opposed to the expression 2+2. This is the first issue, I guess.
If you want it correctly parsed you need to add an sep = "\n" argument to paste or manually add the newline breaks.
I.e.
## R Markdown
```{r, results='asis',echo=FALSE}
txt <- paste("```{r}\n",
2+2,
"\n```", sep = "")
pander::pander(txt)
```
This evalutates to
```{r}
4
```
which is interpreted as R code in the markdown document.
Is there a way of showing formatter R output in rmarkdown/knitr when using results = 'asis'?
An example would be the following function:
myfun <- function() {
cat("hello!\n")
cat(c("one" = 1, "two" = 2))
}
Then, this chunk will print the second cat on a new row:
```{r}
myfun()
```
But this will ignore the formatting from myfun:
```{r, results = "asis"}
myfun()
```
Is there a way of keeping results='asis' but at the same time keep the output of myfun formatted as intended?
You can use the knitr chunk option results = "asis" if you are happy to add two or more spaces at the end of the line. That is, instead of "hello\n", you need to write "hello \n" to trigger the line break.
Example R Markdown code:
---
output: html_document
---
```{r}
myfun <- function() {
cat("hello! \n")
cat(c("one" = 1, "two" = 2))
}
```
```{r results = "asis"}
myfun()
```
Gives
Why the blank spaces? It's because two spaces at the end of a line are used to indicate a hard line break in markdown. For example, this quote is taken from Pandoc's Markdown (which is the default markdown flavour R Markdown uses):
Paragraphs
A paragraph is one or more lines of text followed by one or more blank lines. Newlines are treated as spaces, so you can reflow your paragraphs as you like. If you need a hard line break, put two or more spaces at the end of a line.
I'm after a way to render an Rmd document (that contains references to various "child" files) to a self-contained R Notebook without these dependencies.
At the moment, the .Rmd code chunks are located throughout a number of .R, .py and .sql files and are referenced in the report using
```{r extraction, include=FALSE, cache=FALSE}
knitr::read_chunk("myscript.R")
```
followed by
```{r chunk_from_myscript}
```
as documented here.
I've done this to avoid code duplication and to allow for running the source files separately however these code chunks are only executable in the report via a call to knit or render (when read_chunk is run and the code chunk is available).
Is there a way to spin-off an Rmd (prior to knitting) with
just these chunks populated?
This function
rmarkdown::render("report.Rmd", clean = FALSE)
almost gets there as it leaves the markdown files behind whilst removing extraction and populating chunk_from_myscript however as these files are straight markdown, the chunks are no longer executable and the chunk options are missing. It obviously also doesn't include chunks where eval=TRUE, echo=FALSE which would be needed to run the resulting notebook.
I've also looked at knitr::spin however this would mean disseminating the contents of the report to every source file and isn't terribly ideal.
Reprex
report.Rmd
---
title: 'Report'
---
```{r read_chunks, include=FALSE, cache=FALSE}
knitr::read_chunk("myscript.R")
```
Some documentation
```{r chunk_from_myscript}
```
Some more documentation
```{r chunk_two_from_myscript, eval=TRUE, echo=FALSE}
```
myscript.R
#' # MyScript
#'
#' This is a valid R source file which is formatted
#' using the `knitr::spin` style comments and code
#' chunks.
#' The file's code can be used in large .Rmd reports by
#' extracting the various chunks using `knitr::read_chunk` or
#' it can be spun into its own small commented .Rmd report
#' using `knitr::spin`
# ---- chunk_from_myscript
sessionInfo()
#' This is the second chunk
# ---- chunk_two_from_myscript
1 + 1
Desired Output
notebook.Rmd
---
title: 'Report'
---
Some documentation
```{r chunk_from_myscript}
sessionInfo()
```
Some more documentation
```{r chunk_two_from_myscript, eval=TRUE, echo=FALSE}
1 + 1
```
Working through your reprex I now better understand the issue you are trying to solve. You can knit into an output.Rmd to merge your report and scripts into a single markdown file.
Instead of using knitr::read_chunk, I've read in with knitr::spin to cat the asis output into another .Rmd file. Also note the params$final flag to allow rendering the final document when set as TRUE or allowing the knit to an intermediate .Rmd as FALSE by default.
report.Rmd
---
title: "Report"
params:
final: false
---
```{r load_chunk, include=FALSE}
chunk <- knitr::spin(text = readLines("myscript.R"), report = FALSE, knit = params$final)
```
Some documentation
```{r print_chunk, results='asis', echo=FALSE}
cat(chunk, sep = "\n")
```
to produce the intermediate file:
rmarkdown::render("report.Rmd", "output.Rmd")
output.Rmd
---
title: "Report"
---
Some documentation
```{r chunk_from_myscript, echo=TRUE}
sessionInfo()
```
With the secondary output.Rmd, you could continue with my original response below to render to html_notebook so that the document may be shared without needing to regenerate but still containing the source R markdown file.
To render the final document from report.Rmd you can use:
rmarkdown::render("report.Rmd", params = list(final = TRUE))
Original response
You need to include additional arguments to your render statement.
rmarkdown::render(
input = "output.Rmd",
output_format = "html_notebook",
output_file = "output.nb.html"
)
When you open the .nb.html file in RStudio the embedded .Rmd will be viewable in the editing pane.
Since neither knitr::knit nor rmarkdown::render seem suited to rendering to R markdown, I've managed to somewhat work around this by dynamically inserting the chunk text into each empty chunk and writing that to a new file:
library(magrittr)
library(stringr)
# Find the line numbers of every empty code chunk
get_empty_chunk_line_nums <- function(file_text){
# Create an Nx2 matrix where the rows correspond
# to code chunks and the columns are start/end line nums
mat <- file_text %>%
grep(pattern = "^```") %>%
matrix(ncol = 2, byrow = TRUE)
# Return the chunk line numbers where the end line number
# immediately follows the starting line (ie. chunk is empty)
empty_chunks <- mat[,1] + 1 == mat[,2]
mat[empty_chunks, 1]
}
# Substitute each empty code chunk with the code from `read_chunk`
replace_chunk_code <- function(this_chunk_num) {
this_chunk <- file_text[this_chunk_num]
# Extract the chunk alias
chunk_name <- stringr::str_match(this_chunk, "^```\\{\\w+ (\\w+)")[2]
# Replace the closing "```" with "<chunk code>\n```"
chunk_code <- paste0(knitr:::knit_code$get(chunk_name), collapse = "\n")
file_text[this_chunk_num + 1] %<>% {paste(chunk_code, ., sep = "\n")}
file_text
}
render_to_rmd <- function(input_file, output_file, source_files) {
lapply(source_files, knitr::read_chunk)
file_text <- readLines(input_file)
empty_chunks <- get_empty_chunk_line_nums(file_text)
for (chunk_num in empty_chunks){
file_text <- replace_chunk_code(file_text, chunk_num)
}
writeLines(file_text, output_file)
}
source_files <- c("myscript.R")
render_to_rmd("report.Rmd", "output.Rmd", source_files)
This has the added benefits of preserving chunk options and working
with Python and SQL chunks too since there is no requirement to evaluate
any chunks in this step.
I am trying to figure out how to create a loop that inserts some text into the rmarkdown file, and then produces the graph or table that corresponds to that header. The following is how I picture it working:
for(i in 1:max(month)){
### `r month.name[i]` Air quaility
```{r, echo=FALSE}
plot(airquality[airquality$Month == 5,])
```
}
This ofcourse just prints the for loop as text, if i surround the for loop with r`` I would just get an error.
I want the code to produce an rmd file that looks like this:
May Air Quality
Plot
June Air Quality
Plot
and so on and so forth.
Any ideas? I cannot use latex because I at my work they do not let us download exe files, and I do not know how to use latex anyways. I want to produce a word document.
You can embed the markdown inside the loop using cat().
Note: you will need to set results="asis" for the text to be rendered as markdown.
Note well: you will need two spaces in front of the \n new line character to get knitr to properly render the markdown in the presence of a plot out.
# Monthly Air Quality Graphs
```{r pressure,fig.width=6,echo=FALSE,message=FALSE,results="asis"}
attach(airquality)
for(i in unique(Month)) {
cat(" \n###", month.name[i], "Air Quaility \n")
#print(plot(airquality[airquality$Month == i,]))
plot(airquality[airquality$Month == i,])
cat(" \n")
}
```
As mentioned here, you could also make use of the pander package:
# Monthly Air Quality Graphs
```{r pressure2, fig.width=6, echo=FALSE, message=FALSE, results="asis"}
library(pander)
for (i in unique(airquality$Month)) {
# Inserts Month titles
pander::pandoc.header(month.name[i], level = 3)
# Section contents
plot(airquality[airquality$Month == i,])
# adding also empty lines, to be sure that this is valid Markdown
pander::pandoc.p('')
pander::pandoc.p('')
}
```
Under some conditions I find it helpful to write a loop that writes chunk code rather than write a chunk that runs a loop. Weird solution but it has worked for me beautifully in the past when a bare bones set of chunks is all I need. For your airquality case it would look like this:
## model chunk ##
# ## May Air Quality
# ```{r May}
#
# plot(airquality[airquality$Month == 5,])
#
# ```
# all months in airquality
aqmonths <- c("May",
"June",
"July",
"August",
"September")
for (m in aqmonths) {
cat(
paste0(
"## ", m, " Air Quality",
"\n\n",
"```{r ", m, "}",
"\n\n",
"plot(airquality[airquality$Month == ", match(m, months), ",])",
"\n\n",
"```",
"\n\n"
)
)
}
This will print code for all 5 chunks to the console, and then I can copy and paste into a .Rmd document. It is possible to include any chunk options such as captions or fig arguments in the chunk-writing loop as well. Depending on what else you try to bring in, using functions like match() as in the example is often helpful.
Pros: Preserves ability to use cross-references and set individual captions or options.
Cons: Making changes to all chunks usually requires re-copying the entire output of the chunk-writing loop, which can be tiresome and a bit unwieldy.
What about reusing the chunks inside a loop using <<label>> as described here: https://bookdown.org/yihui/rmarkdown-cookbook/reuse-chunks.html
Label your chunk, set eval=F
```{r my_chunk, echo=FALSE, eval=F}
plot(airquality[airquality$Month == 5,])
```
Then loop
for(i in 1:max(month)){
<<my_chunk>>
}
As known in RMarkdown code chunks can be named like this:
```{r chunkname}
plot(x,y)
```
Is it possible to showing chunkname in output document?
You can use knitr::opts_current$get()$label
example:
```{r cars}
library(knitr)
opts_current$get()$label
plot(cars)
```
It will also work outside of a chunk, in an inline r code. It will then output the label of the last chunk.
You can of course save the labels in a vector to use them later, for instance with a custom hook:
```{r knitr_setup}
library(knitr)
ll <- opts_current$get()$label
knit_hooks$set(label_list = function(before, options, envir) {
if(before) ll <<- c(ll,opts_current$get()$label)
})
opts_chunk$set(label_list=TRUE)
```
ll will then contain the list of chunk labels. However, you cannot access the names of chunks not yet ran.