Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knitr: Add figure notes

I have a figure that looks like this:

<<foo, fig.lp='', fig.cap='name', fig.subcap=c('left', 'right'),>>=
plot1
plot2
@

Now I would like to display a set of notes about this figure right below (i.e. a multiline text). Is there any convenient way to do this within the figure environment created by knitr?


As already pointed out in the comments above, there is currently no solution to my problem. I have filed a feature request.

like image 650
JBDonges Avatar asked Mar 16 '16 21:03

JBDonges


People also ask

How do you add a figure in R markdown?

To add an image in markdown you must stop text editing, and you do this with the command [Alt text] precedeed by a ! Then you have to add the path to the image in brackets. The path to the image is the path from your directory to the image.

How do you show output in R markdown in knitting?

Rendering output Better still, use the “Knit” button in the RStudio IDE to render the file and preview the output with a single click or keyboard shortcut (⇧⌘K).

What does ## do in R markdown?

Text: Also on this page, one can see text sections, for example, one section starts with “## R Markdown” this section will render as text when the PDF of this file is produced and all of the formattings that the user will learn generally applies to this section.

How do I caption a table in R markdown?

You can add a caption to the table via the caption argument, e.g. (see Table 10.1 for the output), knitr::kable(iris2, caption = "An example table caption.") TABLE 10.1: An example table caption.


3 Answers

I know this is a really late answer but here is what I ended up doing for the same type of a problem.

I defined a custom hook that would plot the image as I want it

# Custom knitr hook to add notes to the plot
knit_hooks$set(plot = function(x, options) {
  paste("\n\\end{kframe}\n\\begin{figure}\n",
        "\\includegraphics[width=\\maxwidth]{",
        opts_knit$get("base.url"), paste(x, collapse = "."),
        "}\n",
        "\\textsc{Note} -- here is some car stuff with notes",
        "\\caption{", options$fig.cap, "}\n",
        "\n\\end{figure}\n\\begin{kframe}\n",
        sep = '')
})

Here is the full .Rnw

\documentclass{article}

\usepackage[font=large,labelfont=sc]{caption}

\begin{document}

<<setup, echo=FALSE, message=FALSE, results='hide'>>=
suppressPackageStartupMessages({
  library(ggplot2)
})

opts_chunk$set(echo=FALSE)
opts_chunk$set(results="hide")
@

<<foo, fig.cap='with notes', fig.height=4, fig.width=6>>=
# save a regular plotting function
regular_plot <- knit_hooks$get("plot")

# Custom knitr hook to add notes to the plot
knit_hooks$set(plot = function(x, options) {
  paste("\n\\end{kframe}\n\\begin{figure}\n",
        "\\includegraphics[width=\\maxwidth]{",
        opts_knit$get("base.url"), paste(x, collapse = "."),
        "}\n",
        "\\textsc{Note} -- here is some car stuff with notes",
        "\\caption{", options$fig.cap, "}\n",
        "\n\\end{figure}\n\\begin{kframe}\n",
        sep = '')
})

ggplot(data = mtcars) + geom_point(aes(disp,mpg))
@

<<bar, fig.cap='without notes', fig.height=4, fig.width=6>>=
# restore regular plotting function
knit_hooks$set(plot = regular_plot)

ggplot(data = mtcars) + geom_point(aes(disp,mpg))
@

\end{document}

and here is the resulting PDF:

enter image description here

like image 80
akhmed Avatar answered Sep 28 '22 17:09

akhmed


akhmed answer was absolutely amazing!

I made an slighly modification for Rmd to get caption first and to generalize for every chunk in the document.

We have to add these lines at the beginning:

knit_hooks$set(plot = function(x, options, .notes = notes, .sources = sources) {
  paste("\n\n\\begin{figure}\n",
        "\\includegraphics[width=\\maxwidth]{",
        opts_knit$get("base.url"), paste(x, collapse = "."),
        "}\n",
        "\\caption{",options$fig.cap,"}","\\label{fig:",opts_current$get("label"),"}","\\textsc{}",
        "\n\\textsc{Notas} -- ",.notes,
        "\n\\textsc{Fuentes} -- ", .sources,
        "\n\\end{figure}\n",
        sep = '')
})

Then in every chunk we only write the notes and sources of the plot

notes = "Notes to explain the plot"
sources = "Explain the sources"

Again, thanks a lot akhmed!!

Pd: I use "\\textsc{}" to generate an space among caption and notes & sources.

It would be nice to generalize this to use subcaptions with many figures in the same plot.

like image 27
Frederich Avatar answered Sep 28 '22 17:09

Frederich


The solution from @akhmed was enormously helpful for me. I needed to make a few additional customizations which I pass along as an answer (it was too long for a comment).

  • First, I wanted a little more control over the margins for the note and found adding the minipage environment helped (\\begin{minipage} below set at 6 inches wide).
  • Second, I added a couple of minor formatting additions by setting a typeface size and left justifying the text (\\small and \\begin{flushleft} below).

  • Finally, for some figures, I wanted to use the fig.pos="h!" or figure position = "here" option of Knitr / Latex and it took me a minute to realize that this hook overwrites that chunk option so I manually added it as \\begin{figure}[h!].

Again, my thanks to @akhmed for offering this solution.

knit_hooks$set(plot = function(x, options) {
    paste("\n\\end{kframe}\n\\begin{figure}[h!]\n",
      "\\includegraphics[width=\\maxwidth]{",
      opts_knit$get("base.url"), paste(x, collapse = "."),
      "}\n",
      "\\begin{minipage}{6in}\\small\\begin{flushleft}Note: Lorem ipsum \\end{flushleft}\\end{minipage}",
      "\\caption{", options$fig.cap, " \\label{", options$fig.lp, opts_current$get("label"), "}}\n",
      "\n\\end{figure}\n\\begin{kframe}\n",
      sep = '')
    })
like image 26
Omar Wasow Avatar answered Sep 28 '22 17:09

Omar Wasow