figure captions, references using knitr and markdown to html - r

I'm writing an Rmd file, to be processed by knitr into HTML. It contains some R chunks that generate figures, which get stored as data URIs in HTML.
1) How do I add a caption to such an image? I'd like to have a caption that says something like "Figure 3: blah blah blah", where the "3" is automatically generated.
2) How do I later on reference this image, i.e., "as you can see in Figure 3, blah blah".

I'm late to the party, but I wanted to mention a small package I recently built to do figure captioning and cross-referencing with knitr. It is called kfigr and you can install it using devtools::install_github('mkoohafkan/kfigr'). It is still in active development but the main functionality is there. Be sure to check out the vignette, it shows some usage examples and defines some hooks for figure captions and anchors (I may later choose to have the package import knitr and define those hooks on load).
EDIT: kfigr is now available on CRAN!

You can create the figure numbers with a simple counter in R; see one example here. The problem is whether the markdown renderer will render the figure caption for you: R Markdown v1 won't, but v2 (based on Pandoc) will.
I do not know. There is no direct way to insert a label as an identifier for figures, so it is probably not possible to cross reference figures with pure Markdown. Once you've got issues like this, think (1) do I really need it? (2) if it is intended to be a document with a complicated structure, I think it is better to use LaTeX directly (Rnw documents).

Also very late to the party I changed Yihuis suggestion here that he also linked above to do referencing.
```{r functions, include=FALSE}
# A function for captioning and referencing images
fig <- local({
i <- 0
ref <- list()
list(
cap=function(refName, text) {
i <<- i + 1
ref[[refName]] <<- i
paste("Figure ", i, ": ", text, sep="")
},
ref=function(refName) {
ref[[refName]]
})
})
```
```{r cars, echo=FALSE, fig.cap=fig$cap("cars", "Here you see some interesting stuff about cars and such.")}
plot(cars)
```
What you always wanted to know about cars is shown in figure `r fig$ref("cars")`

One way to do both of these is described here: http://rmflight.github.io/posts/2012/10/papersinRmd.html
Another is described here (but I don't know if it does your #2). http://gforge.se/2014/01/fast-track-publishing-using-knitr-part-iii/

Another solution:
https://github.com/adletaw/captioner
From the README:
captioner() returns a captioner function for each set of figures, tables, etc. that you want to create. See the help files for more details.
For example:
> fig_nums <- captioner()
> fig_nums("my_pretty_figure", "my pretty figure's caption")
"Figure 1: my pretty figure's caption"
> fig_nums("my_pretty_figure", cite = TRUE)

I did both (figure numbers + references) with bookdown. I added in output section in the header of the file:
output:
bookdown::html_document2:
fig_caption : TRUE
Then I created a figure in a R code chunk like follows:
{r, my-fig-label,echo=F, eval=T, fig.align = 'center', fig.cap="This is my caption"}
knitr::include_graphics(here::here("images", "my_image.png"))
This produces an automatic number under your figure. You can refer to it with \#ref(fig:my-fig-label).

Using the official bookdown documentation 4.10 Numbered figure captions:
---
output: bookdown::html_document2
---
```{r cars, fig.cap = "An amazing plot"}
plot(cars)
```
```{r mtcars, fig.cap = "Another amazing plot"}
plot(mpg ~ hp, mtcars)
```

Related

Editing stargazer source code -- saved edits don't render to pdf

So I'm also preparing a table or regression results in stargazer, and I'm only showing the t-scores in the table from 10 different models side by side. I have the same question as in this earlier post on how to remove the "t = " from the stargazer results output from #deca.
I've followed the answer given by #JNWHH, which is:
Access the edit-screen of the stargazer function with trace(stargazer:::.stargazer.wrap, edit = T)
Go to line 7103/7104 (may be different depending on your stargazer version) and look for .format.t.stats.left <- "t = " and .format.t.stats.right <- "" and edit it to your liking, e.g., .format.t.stats.left <- "[" and .format.t.stats.right <- "]"
Confirm with "save".
After completing these three steps and then calling the stargazer function again, I can see in the LaTeX code produced for my table that all of the "t = " have been removed. However, when I knit the document, the resulting PDF still has the "t = " in them.
I wasn't sure what/if code was needed here for people to diagnose, but if so, please let me know and I can try to include what I'm running. But really, I'm just following the three steps above exactly as described. I have not restarted my R-session since editing the source code, so I don't think the problem stems from that. If I'm missing something obvious, thanks for letting me know.
I gone through the solution. You have to adjust the stargazer source code while knitting the document. This is true for either text in html or latex in PDF output.
---
title: "stargazer_edits"
author: "Me"
date: "2023-01-13"
output:
html_document: default
pdf_document: default
---
## stargazer source edited
```{r, echo=FALSE, warning=FALSE, message=FALSE}
library(stargazer)
# I do this once
trace(stargazer:::.stargazer.wrap, edit = T)
model <- lm(mpg ~ disp + cyl, data=mtcars)
stargazer(model, type = "text", report = "vc*t")
```
While producing the document this opens the source code.
You can more easily find the part .format.t.stats.left (lines 7105 and 7106 at 13.01.2023) by searching the text file. You modify the style, e.g. change it to square brackets.

R Markdown tufte knitting gives "Error: pandoc document conversion failed with error 5"

System Details
RStudio Version : 1.1.442,
OS Version : Windows 7 Professional,
R Version : 3.4.4,
rmarkdown : 1.9,
knitr : 1.20,
tufte : 0.3
Steps to reproduce the problem
Knit to tufte_book the following default template. It won't knit and instead I get an "Error: pandoc document conversion failed with error 5". I have reinstalled R Studio, updated to R 3.4.4 and updated all my packages with update.packages().
Also - I am able to knit to tufte_html and tufte_handout, it's just tufte_book that gives the error.
---
title: "Tufte Handout"
subtitle: "An implementation in R Markdown"
author: "JJ Allaire and Yihui Xie"
date: "`r Sys.Date()`"
output:
tufte::tufte_book:
citation_package: natbib
latex_engine: xelatex
tufte::tufte_handout:
citation_package: natbib
latex_engine: xelatex
tufte::tufte_html: default
bibliography: skeleton.bib
link-citations: yes
---
```{r setup, include=FALSE}
library(tufte)
# invalidate cache when the tufte version changes
knitr::opts_chunk$set(tidy = FALSE, cache.extra = packageVersion('tufte'))
options(htmltools.dir.version = FALSE)
```
# Introduction
The Tufte handout style is a style that Edward Tufte uses in his books and handouts. Tufte's style is known for its extensive use of sidenotes, tight integration of graphics with text, and well-set typography. This style has been implemented in LaTeX and HTML/CSS^[See Github repositories [tufte-latex](https://github.com/tufte-latex/tufte-latex) and [tufte-css](https://github.com/edwardtufte/tufte-css)], respectively. We have ported both implementations into the [**tufte** package](https://github.com/rstudio/tufte). If you want LaTeX/PDF output, you may use the `tufte_handout` format for handouts, and `tufte_book` for books. For HTML output, use `tufte_html`. These formats can be either specified in the YAML metadata at the beginning of an R Markdown document (see an example below), or passed to the `rmarkdown::render()` function. See #R-rmarkdown more information about **rmarkdown**.
```yaml
---
title: "An Example Using the Tufte Style"
author: "John Smith"
output:
tufte::tufte_handout: default
tufte::tufte_html: default
---
```
There are two goals of this package:
1. To produce both PDF and HTML output with similar styles from the same R Markdown document;
1. To provide simple syntax to write elements of the Tufte style such as side notes and margin figures, e.g. when you want a margin figure, all you need to do is the chunk option `fig.margin = TRUE`, and we will take care of the details for you, so you never need to think about `\begin{marginfigure} \end{marginfigure}` or `<span class="marginfigure"> </span>`; the LaTeX and HTML code under the hood may be complicated, but you never need to learn or write such code.
If you have any feature requests or find bugs in **tufte**, please do not hesitate to file them to https://github.com/rstudio/tufte/issues. For general questions, you may ask them on StackOverflow: http://stackoverflow.com/tags/rmarkdown.
# Headings
This style provides first and second-level headings (that is, `#` and `##`), demonstrated in the next section. You may get unexpected output if you try to use `###` and smaller headings.
`r newthought('In his later books')`^[[Beautiful Evidence](http://www.edwardtufte.com/tufte/books_be)], Tufte starts each section with a bit of vertical space, a non-indented paragraph, and sets the first few words of the sentence in small caps. To accomplish this using this style, call the `newthought()` function in **tufte** in an _inline R expression_ `` `r ` `` as demonstrated at the beginning of this paragraph.^[Note you should not assume **tufte** has been attached to your R session. You should either `library(tufte)` in your R Markdown document before you call `newthought()`, or use `tufte::newthought()`.]
# Figures
## Margin Figures
Images and graphics play an integral role in Tufte's work. To place figures in the margin you can use the **knitr** chunk option `fig.margin = TRUE`. For example:
```{r fig-margin, fig.margin = TRUE, fig.cap = "MPG vs horsepower, colored by transmission.", fig.width=3.5, fig.height=3.5, cache=TRUE, message=FALSE}
library(ggplot2)
mtcars2 <- mtcars
mtcars2$am <- factor(
mtcars$am, labels = c('automatic', 'manual')
)
ggplot(mtcars2, aes(hp, mpg, color = am)) +
geom_point() + geom_smooth() +
theme(legend.position = 'bottom')
```
Note the use of the `fig.cap` chunk option to provide a figure caption. You can adjust the proportions of figures using the `fig.width` and `fig.height` chunk options. These are specified in inches, and will be automatically scaled down to fit within the handout margin.
## Arbitrary Margin Content
In fact, you can include anything in the margin using the **knitr** engine named `marginfigure`. Unlike R code chunks ```` ```{r} ````, you write a chunk starting with ```` ```{marginfigure} ```` instead, then put the content in the chunk. See an example on the right about the first fundamental theorem of calculus.
```{marginfigure}
We know from _the first fundamental theorem of calculus_ that for $x$ in $[a, b]$:
$$\frac{d}{dx}\left( \int_{a}^{x} f(u)\,du\right)=f(x).$$
```
For the sake of portability between LaTeX and HTML, you should keep the margin content as simple as possible (syntax-wise) in the `marginefigure` blocks. You may use simple Markdown syntax like `**bold**` and `_italic_` text, but please refrain from using footnotes, citations, or block-level elements (e.g. blockquotes and lists) there.
Note: if you set `echo = FALSE` in your global chunk options, you will have to add `echo = TRUE` to the chunk to display a margin figure, for example ```` ```{marginfigure, echo = TRUE} ````.
## Full Width Figures
You can arrange for figures to span across the entire page by using the chunk option `fig.fullwidth = TRUE`.
```{r fig-fullwidth, fig.width = 10, fig.height = 2, fig.fullwidth = TRUE, fig.cap = "A full width figure.", warning=FALSE, message=FALSE, cache=TRUE}
ggplot(diamonds, aes(carat, price)) + geom_smooth() +
facet_grid(~ cut)
```
Other chunk options related to figures can still be used, such as `fig.width`, `fig.cap`, `out.width`, and so on. For full width figures, usually `fig.width` is large and `fig.height` is small. In the above example, the plot size is $10 \times 2$.
## Main Column Figures
Besides margin and full width figures, you can of course also include figures constrained to the main column. This is the default type of figures in the LaTeX/HTML output.
```{r fig-main, fig.cap = "A figure in the main column.", cache=TRUE}
ggplot(diamonds, aes(cut, price)) + geom_boxplot()
```
# Sidenotes
One of the most prominent and distinctive features of this style is the extensive use of sidenotes. There is a wide margin to provide ample room for sidenotes and small figures. Any use of a footnote will automatically be converted to a sidenote. ^[This is a sidenote that was entered using a footnote.]
If you'd like to place ancillary information in the margin without the sidenote mark (the superscript number), you can use the `margin_note()` function from **tufte** in an inline R expression. `r margin_note("This is a margin note. Notice that there is no number preceding the note.")` This function does not process the text with Pandoc, so Markdown syntax will not work here. If you need to write anything in Markdown syntax, please use the `marginfigure` block described previously.
# References
References can be displayed as margin notes for HTML output. For example, we can cite R here [#R-base]. To enable this feature, you must set `link-citations: yes` in the YAML metadata, and the version of `pandoc-citeproc` should be at least 0.7.2. You can always install your own version of Pandoc from http://pandoc.org/installing.html if the version is not sufficient. To check the version of `pandoc-citeproc` in your system, you may run this in R:
```{r eval=FALSE}
system2('pandoc-citeproc', '--version')
```
If your version of `pandoc-citeproc` is too low, or you did not set `link-citations: yes` in YAML, references in the HTML output will be placed at the end of the output document.
# Tables
You can use the `kable()` function from the **knitr** package to format tables that integrate well with the rest of the Tufte handout style. The table captions are placed in the margin like figures in the HTML output.
```{r}
knitr::kable(
mtcars[1:6, 1:6], caption = 'A subset of mtcars.'
)
```
# Block Quotes
We know from the Markdown syntax that paragraphs that start with `>` are converted to block quotes. If you want to add a right-aligned footer for the quote, you may use the function `quote_footer()` from **tufte** in an inline R expression. Here is an example:
> "If it weren't for my lawyer, I'd still be in prison. It went a lot faster with two people digging."
>
> `r tufte::quote_footer('--- Joe Martin')`
Without using `quote_footer()`, it looks like this (the second line is just a normal paragraph):
> "Great people talk about ideas, average people talk about things, and small people talk about wine."
>
> --- Fran Lebowitz
# Responsiveness
The HTML page is responsive in the sense that when the page width is smaller than 760px, sidenotes and margin notes will be hidden by default. For sidenotes, you can click their numbers (the superscripts) to toggle their visibility. For margin notes, you may click the circled plus signs to toggle visibility.
# More Examples
The rest of this document consists of a few test cases to make sure everything still works well in slightly more complicated scenarios. First we generate two plots in one figure environment with the chunk option `fig.show = 'hold'`:
```{r fig-two-together, fig.cap="Two plots in one figure environment.", fig.show='hold', cache=TRUE, message=FALSE}
p <- ggplot(mtcars2, aes(hp, mpg, color = am)) +
geom_point()
p
p + geom_smooth()
```
Then two plots in separate figure environments (the code is identical to the previous code chunk, but the chunk option is the default `fig.show = 'asis'` now):
```{r fig-two-separate, ref.label='fig-two-together', fig.cap=sprintf("Two plots in separate figure environments (the %s plot).", c("first", "second")), cache=TRUE, message=FALSE}
```
You may have noticed that the two figures have different captions, and that is because we used a character vector of length 2 for the chunk option `fig.cap` (something like `fig.cap = c('first plot', 'second plot')`).
Next we show multiple plots in margin figures. Similarly, two plots in the same figure environment in the margin:
```{r fig-margin-together, fig.margin=TRUE, fig.show='hold', fig.cap="Two plots in one figure environment in the margin.", fig.width=3.5, fig.height=2.5, cache=TRUE}
p
p + geom_smooth(method = 'lm')
```
Then two plots from the same code chunk placed in different figure environments:
```{r fig-margin-separate, fig.margin=TRUE, fig.cap=sprintf("Two plots in separate figure environments in the margin (the %s plot).", c("first", "second")), fig.width=3.5, fig.height=2.5, cache=TRUE}
knitr::kable(head(iris, 15))
p
knitr::kable(head(iris, 12))
p + geom_smooth(method = 'lm')
knitr::kable(head(iris, 5))
```
We blended some tables in the above code chunk only as _placeholders_ to make sure there is enough vertical space among the margin figures, otherwise they will be stacked tightly together. For a practical document, you should not insert too many margin figures consecutively and make the margin crowded.
You do not have to assign captions to figures. We show three figures with no captions below in the margin, in the main column, and in full width, respectively.
```{r fig-nocap-margin, fig.margin=TRUE, fig.width=3.5, fig.height=2, cache=TRUE}
# a boxplot of weight vs transmission; this figure
# will be placed in the margin
ggplot(mtcars2, aes(am, wt)) + geom_boxplot() +
coord_flip()
```
```{r fig-nocap-main, cache=TRUE}
# a figure in the main column
p <- ggplot(mtcars, aes(wt, hp)) + geom_point()
p
```
```{r fig-nocap-fullwidth, fig.fullwidth=TRUE, fig.width=10, fig.height=3, cache=TRUE}
# a fullwidth figure
p + geom_smooth(method = 'lm') + facet_grid(~ gear)
```
# Some Notes on Tufte CSS
There are a few other things in Tufte CSS that we have not mentioned so far. If you prefer `r sans_serif('sans-serif fonts')`, use the function `sans_serif()` in **tufte**. For epigraphs, you may use a pair of underscores to make the paragraph italic in a block quote, e.g.
> _I can win an argument on any topic, against any opponent. People know this, and steer clear of me at parties. Often, as a sign of their great respect, they don't even invite me._
>
> `r quote_footer('--- Dave Barry')`
We hope you will enjoy the simplicity of R Markdown and this R package, and we sincerely thank the authors of the Tufte-CSS and Tufte-LaTeX projects for developing the beautiful CSS and LaTeX classes. Our **tufte** package would not have been possible without their heavy lifting.
You can turn on/off some features of the Tufte style in HTML output. The default features enabled are:
```yaml
output:
tufte::tufte_html:
tufte_features: ["fonts", "background", "italics"]
```
If you do not want the page background to be lightyellow, you can remove `background` from `tufte_features`. You can also customize the style of the HTML page via a CSS file. For example, if you do not want the subtitle to be italic, you can define
```css
h3.subtitle em {
font-style: normal;
}
```
in, say, a CSS file `my_style.css` (under the same directory of your Rmd document), and apply it to your HTML output via the `css` option, e.g.,
```yaml
output:
tufte::tufte_html:
tufte_features: ["fonts", "background"]
css: "my_style.css"
```
There is also a variant of the Tufte style in HTML/CSS named "[Envisoned CSS](http://nogginfuel.com/envisioned-css/)". This style can be used by specifying the argument `tufte_variant = 'envisioned'` in `tufte_html()`^[The actual Envisioned CSS was not used in the **tufte** package. We only changed the fonts, background color, and text color based on the default Tufte style.], e.g.
```yaml
output:
tufte::tufte_html:
tufte_variant: "envisioned"
```
To see the R Markdown source of this example document, you may follow [this link to Github](https://github.com/rstudio/tufte/raw/master/inst/rmarkdown/templates/tufte_html/skeleton/skeleton.Rmd), use the wizard in RStudio IDE (`File -> New File -> R Markdown -> From Template`), or open the Rmd file in the package:
```{r eval=FALSE}
file.edit(
tufte:::template_resources(
'tufte_html', '..', 'skeleton', 'skeleton.Rmd'
)
)
```
This document is also available in [Chinese](http://rstudio.github.io/tufte/cn/), and its `envisioned` style can be found [here](http://rstudio.github.io/tufte/envisioned/).
```{r bib, include=FALSE}
# create a bib file for the R packages used in this document
knitr::write_bib(c('base', 'rmarkdown'), file = 'skeleton.bib')
```

Solutions to Exercises in Bookdown

How should I code solutions to exercises in the book I am writing using the bookdown package?
I'm currently writing a book using the bookdown R package. The book is broken down into chapters, and each chapter has exercises in a markdown numbered list. I would like to be able to put the solutions directly under the exercises without messing up the numbering of the problems, and in such a way that I can toggle whether the solutions are printed. I would also like to be able to pull out selected solutions (or all solutions) to form a solutions manual that gets printed out as an appendix. So far, I have two methods, which I call the "hidden R chunk method" and the "YAML method" but neither seems ideal, and can only be used to create a solutions manual.
1. Exercise one compute 1+1.
```{r, echo = FALSE, eval = FALSE}
#Solution
1+1
#BeginText The solution is `r 1 + 1`.
#EndText
```
1. Exercise two: compute 2^2.
```{r, echo = FALSE, eval = FALSE}
#Solution
2*2
#BeginText The solution is $2^2 = $`r 2*2`.
#EndText
```
I then wrote a script that pulls out anything with the #Solution comment, and breaks the #BeginText and #EndText out like this:
###Problem 1.
```{r }
1+1
```
The solution is `r 1 + 1`.
###Problem 2.
```{r }
2*2
```
The solution is $2^2 = $`r 2*2`.
and saves that in a new .Rmd file with appropriate headers.
The second solution involves YAML in between the exercises.
1. Exercise one compute 1+1.
---
solution: |
```{r}
1+1
```
The solution is `r 1 + 1`.
---
My co-author had hoped that he could pull out the YAML using an existing parser, but ended up having to write a script just like the hidden R chunk method. I'm not sure how bad of an idea it is to use YAML like this. Both solutions require that each exercise have at least a solution stub in order for the numbering to be the same.
I would like the solutions of the exercises to be connected to the exercise in some way, so that if we re-arrange the exercises or add new exercises, nothing breaks. I would also like to be able to pull out some or all of the solutions into separate markdown files that we can use to create a solutions manual.
How should we do this?

Format text inside R code chunk

I am making some slides inside Rstudio following instructions here:
http://rmarkdown.rstudio.com/beamer_presentation_format.html
How do I define text size, colors, and "flow" following numbers into two columns?
```{r,results='asis', echo=FALSE}
rd <- sample(x=1e6:1e7, size = 10, replace = FALSE)
cat(rd, sep = "\n")
```
Output is either HTML (ioslides) or PDF (Beamer)
Update:
Currently the code above will only give something like the following
6683209
1268680
8412827
9688104
6958695
9655315
3255629
8754025
3775265
2810182
I can't do anything to change text size, color or put them into a table. The output of R codechunk is just plain text. Maybe it is possible to put them in a table indeed, as mentioned at this post:
http://tex.aspcode.net/view/635399273629833626273734/dynamically-format-labelscolumns-of-a-latex-table-generated-in-rknitrxtable
But I don't know about text size and color.
Update 2:
The idea weaving native HTML code to R output is very useful. I haven't thought of that. This however only works if I want to output HTML. For PDF output, I have to weave the native Latex code with R output. For example, the code following works using "knitr PDF" output:
```{r,results='asis', echo=FALSE}
cat("\\textcolor{blue}{")
rd <- sample(x=1e6:1e7, size = 10, replace = FALSE)
for (n in rd) {
cat(paste0(n, '\\newline \n')) }
cat("}")
```
You are using results='asis', hence, you can simply use print() and formatting markup. If you want your text to be red, simply do:
```{r,results='asis', echo=FALSE}
print("<div class='red2'>")
rd <- sample(x=1e6:1e7, size = 10, replace = FALSE)
cat(rd, sep = "\n")
print("</div>")
```
Hope it helps.
It sounds as if you want the output to be either PDF or HTML.
One possibility is the xtable package. It produces tables either in PDF or HTML format. There's no (output-independent) way to specify colour, however. Here's an example.
xt <- xtable(data.frame(a=1:10))
print(xt, type="html")
print(xt) # Latex default
Another option is the pandoc.table function from the pander package. You need the pandoc binary installed. If you have RStudio, you have this already. The function spits out some markdown which then can be converted to HTML or PDF by pandoc.
Here's how you could use this from RStudio. Create an RMarkdown document like this:
---
title: "Untitled"
author: "You"
date: "20 November 2014"
output: html_document
---
```{r, results='asis'}
library(pander)
tmp <- data.frame(a=1:10,b=1:10)
pandoc.table(tmp)
```
When you click "knit HTML", it will spit out a nice HTML document. If you change output to pdf_document, it will spit out a nice PDF. You can edit the options to change output - e.g.
pandoc.table(tmp, emphasize.strong.rows=c(2,4,6,8,10))
and this will work both in PDF or HTML. (Still no options to change colour though. Homework task: fix pandoc.table to allow arbitrary colours.)
Under the hood, knitr is writing markdown, and pandoc is converting the markdown to whatever you like.

Conditionally display a block of text in R Markdown

I am using knitr to parse an R Markdown document . Is there a way to conditionally display a block of text in R Markdown depending on a variable in the environment I pass into knitr?
For instance, something like:
`r if(show.text) {`
la la la
`r }`
Would print "la la la" in the resulting doc if show.text is true.
You need a complete R expression, so you cannot break it into multiple blocks like you show, but if the results of a block are a text string then it will be included as is (without quotes), so you should be able to do something like:
`r if(show.text){"la la la"}`
and it will include the text if and only if show.text is TRUE.
You can do this using the "eval" chunk option. See http://yihui.name/knitr/options/.
```{r setup, echo=FALSE}
show_text <- FALSE
````
```{r conditional_block, eval=show_text}
print("this will only print when show.text is TRUE")
```
I've been using YAML config files to parameterize my markdown reports which makes them more reusable.
```{r load_config}
library(yaml)
config <- yaml.load_file("config.yaml")
```
...
```{r conditional_print, eval=config$show_text}
print("la la la")
````
I find it easiest to do this by putting all of my text into a separate file and then include it from the main file with:
```{r conditional_print, child='text.Rmd', eval = show_text}
```
This has the advantage that you can still put inline R statements or other chunks into the child file, so that if you change your mind about what counts as optional text, you don't have to refactor your project.
Here's a tweak to Paul Boardman's approach that gives proper markup in the output.
```{r setup, echo=FALSE}
show_text <- FALSE
```
```{r conditional_block, echo=FALSE, results='asis', eval=show_text}
cat("## Hey look, a heading!
lorem ipsum dolor emet...")
```
Even better, if we invoke the python engine to generate our output, we can use triple quoting to easily handle text that contains single or double quotes without needing to do anything fancy:
```{python, conditional_block_py, echo=FALSE, results='asis', eval=show_cond_text}
print("""
## Still a heading
Block of text with 'single quotes' and "double quotes"
""")
```
The solutions above may be a little clunky for larger blocks of text and not great for certain situations. Let's say I want to create a worksheet for students with some questions and also use the same .Rmd file to generate a file with solutions. I used basic LaTeX flow control:
``` {r, include = F}
# this can be e.g., in a parent .Rmd and the below can be in child
solution <- TRUE
```
\newif\ifsol
\sol`r ifelse(solution, 'true', 'false')`
Then I can do:
What is $2 + 2$
\ifsol
4
\fi
This way you can also create alternative blocks of text using
\ifsol
Alternative 1
\else
Alternative 2
\fi
The accepted answer above works well for inline content.
For block content (one of several paragraphs of Markdown text), knitr contains a asis engine that allow to include Markdown content conditionnally depending if chunk option echo = FALSE or echo = TRUE
Example from the doc https://bookdown.org/yihui/rmarkdown-cookbook/eng-asis.html
```{r}
getRandomNumber <- function() {
sample(1:6, 1)
}
```
```{asis, echo = getRandomNumber() == 4}
According to https://xkcd.com/221/, we just generated
a **true** random number!
```
If you need to include more complexe content , like piece of a R Markdown document with e.g code block, then child document could be useful. See https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html
Another way to add markdown text conditionally is below. It uses the block "engine" which seems to run fine although I'm not sure how to make inline R evaluation working.
Note that I use the view_all switch defined in the YAML metadata to control whether or not the block is visible.
Also, note that both eval and include chunk options are needed.
The first prevents errors during regular Run All in RStudio.
The second prevents output with Knit.
---
title: "Conditional Output"
params:
view_all: false
output:
html_document: default
pdf_document: default
---
```{block eval=FALSE, include=params$view_all}
# Some simple markdown.
Some things work: $2 + 2^2 = 3\cdot2$
Other does not: 2 + 2 = `r 2+2`
```
I tried to define a function my.render(), which preprocesses the Rmd file, and depending on the commentout argument, either keeps the HTML commenting code (TRUE) in the Rmd file or removes them (FALSE). Then writes the preprocessed Rmd file into tmp.Rmd, and uses the usual render() function.
my.render <- function(input, commentout=FALSE, ...) {
if (commentout == FALSE) {
## Delete the HTML comment lines from code
txt <- readLines(input)
txt[grepl(" *<!-- *| *--> *", txt)] <- ""
write.table(txt, file="tmp.Rmd", sep="\n", quote=FALSE, row.names=FALSE, col.names=FALSE)
render("tmp.Rmd", output_file=sub("Rmd","html",input), ...)
} else {
render(input, output_file=sub("Rmd","html",input), ...)
}
}
It seemed to work. E.g.
<!--
This text with formulas $\alpha+\beta$ is visible, when commentout=FALSE.
-->

Resources