JBDonges
JBDonges

Reputation: 316

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.

Upvotes: 8

Views: 2612

Answers (3)

Frish Vanmol
Frish Vanmol

Reputation: 354

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.

Upvotes: 2

Omar Wasow
Omar Wasow

Reputation: 2020

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 = '')
    })

Upvotes: 1

akhmed
akhmed

Reputation: 3635

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

Upvotes: 5

Related Questions