How to control caption placement for figures in KnitR? - r

Is there a way to specify the placement of captions for figures generated by R using KnitR? I'm hoping that there's something functionally equivalent to xtable()'s caption.placement option.
A minimal working example is provided below.
\documentclass[12pt, english, oneside]{amsart}
\begin{document}
The caption for Figure \ref{fig:plot} is placed below the figure. Could we place it above, instead?
<<plot, echo=FALSE, fig.cap="Default caption placement is below the figure.">>=
plot(x=0, y=0)
#
\end{document}

This would likely be best to deal with in the latex style for all figures, but you can customize figures with hooks. The fig.env chunk option controls the environment the block is inserted into. You could always make your own version of figure with your own formatting.

Related

Reference one of several figures in r code chunk of a Rnw file

Creating a parameterized report with an rnw file. I am trying to reference specific figures from a code chunk that has multiple figures in it (generated by a loop through a list of figures). I know if there's a single figure I can reference it from the chunk label with \ref{fig:foo} as Yihui mentions in https://bookdown.org/yihui/bookdown/figures.html . But I cannot seem to reference specific figures in the chunk. I tried referencing the unique figure caption or the chunk as a whole but both give me ??. Is there a way to do this?
I searched this Dynamic LaTeX references in R comment with knitr and its linked questions but wasn't able to make it work.
Also in Figures captions and labels in knitr , the plots are combined into one big plot which bypasses the problem.
MVWE:
\documentclass{article}
\usepackage{float}
\usepackage{hyperref}
\usepackage{caption} % Needs to be after hyperref. jumps you to top of figure not to label.
\begin{document}
<<figures, fig.cap=c('fig1','fig2')>>=
library(knitr)
library(markdown)
library(rmarkdown)
library(ggplot2)
figure1 <- ggplot(mtcars) + geom_point(aes(x=mpg,y=cyl))
figure2 <- ggplot(mtcars) + geom_point(aes(x=drat,y=wt))
plots <- list(figure1,figure2)
plots
#
as we can see in \ref{fig:figures}
\end{document}
Just append a number to it:
as we can see in \ref{fig:figures1} and \ref{fig:figures2}
To figure this out, you should look at the .tex file, which contains
\begin{figure}
\includegraphics[width=\maxwidth]{figure/figures-1} \caption[fig1]{fig1}\label{fig:figures1}
\end{figure}
for the first one, and similar stuff for the other. The \label{fig:figures1} part is what your \ref needs to refer to.

Is it possible to give a figure/plot a label in Sweave? [duplicate]

I can't get R/KnitR to create the LaTeX \label{} statement for a figure. The manual seems to indicate that a \label{} statement will be created by concatenating the string in fig.lp ("fig:" by default) with the label for the R-code chunk. I haven't been able to get this to work, however. No \label{} statement is created for the first figure created by knitting the MWE below. The second figure has it's label added with a workaround that I just discovered, putting the R chunk in a figure environment, and putting the \label tag after or inside the \caption tag.
\documentclass[12pt, english, oneside]{amsart}
\begin{document}
Figure \ref{fig:plot} doesn't have it's label.
<<plot>>=
plot(x=0, y=0)
#
Figure \ref{fig:plot2} has its label.
\begin{figure}
\caption{\label{fig:plot2}}
<<>>=
plot(x=1,y=1)
#
\end{figure}
\end{document}
Okay, I've found a workaround by putting the R chunk in a \begin{figure} . . .\end{figure} environment in LaTeX. I can create the label in that same environment. Still, I'd like to understand how Yihui intends for this to be handled with KnitR.
You need to set fig.cap = '' (or whatever you wish) to ensure that a figure environment is used in the latex document. (you may have noticed that the \begin{figure} ... \end{figure} is missing along with the \label{} component
eg
\documentclass[12pt, english, oneside]{amsart}
\begin{document}
See Figure \ref{fig:plot}.
<<plot, fig.lp="fig:", fig.cap = ''>>=
plot(x=0, y=0)
#
\end{document}
I would agree that the description from the website is less than clear as to this being necessary.
fig.env: ('figure') the LaTeX environment for figures, e.g. set fig.env='marginfigure' to get \begin{marginfigure}
fig.cap: (NULL; character) figure caption to be used in a figure environment in LaTeX (in \caption{}); if NULL or NA, it will be
ignored, otherwise a figure environment will be used for the plots in
the chunk (output in \begin{figure} and \end{figure})
Although the graphics manual is clear, and the reasoning makes sense
Figure Caption
If the chunk option fig.cap is not NULL or NA, the
plots will be put in a figure environment when the output format is
LATEX, and this option is used to write a caption in this environment
using \caption{}. The other two related options are fig.scap and
fig.lp which set the short caption and a prefix string for the figure
label. The default short caption is extracted from the caption by
truncating it at the first period or colon or semi-colon. The label is
a combination of fig.lp and the chunk label. Because figure is a float
environment, it can float away from the chunk output to other places
such as the top or bottom of a page when the TEX document is compiled.
If you were wishing to replicate a R session output, you wouldn't want the figures to float away from the line of code which defines how they were created.

R Bookdown image disappears

I am having an issue with bookdown, not sure the reason why.
When add images (these are files, so I use knitr::include_graphics) like this:
# This is a minimal example
I want the image "mas.gif". Where is it?
```{r mas, echo=F, fig.cap="image", ref.label="fig:mas"}
knitr::include_graphics("mas.gif")
```
Hmmm...no clue!
The chunk just disappears in the epub, md, tex and pdf files.
What could be wrong? It used to work some while ago...
Just remove , ref.label="fig:mas", like this
# This is a minimal example
I want the image "mas.gif". Where is it?
```{r mas, echo=F, fig.cap="image"}
knitr::include_graphics("mas.gif")
```
Hmmm...no clue!
See the documentation by bookdown package's author:
If we assign a figure caption to a code chunk via the chunk option fig.cap, R plots will be put into figure environments, which will be automatically labeled and numbered, and can also be cross-referenced. The label of a figure environment is generated from the label of the code chunk, e.g., if the chunk label is foo, the figure label will be fig:foo (the prefix fig: is added before foo). To reference a figure, use the syntax \#ref(label), where label is the figure label, e.g., fig:foo.

R markdown: can I insert a pdf to the r markdown file as an image?

I am trying to insert a pdf image into an r markdown file. I know it is possible to insert jpg or png images. I was just wondering if it is also possible to insert a pdf image. Thanks very much!
If you are just trying to insert an image that has been exported from, for example, some R analysis into a pdf image, you can also use the standard image options from the knitr engine.
With something like:
```{r, out.width="0.3\\linewidth", include=TRUE, fig.align="center", fig.cap=c("your caption"), echo=FALSE}
knitr::include_graphics("./images/imagename.pdf")
```
Unfortunately you can't specify the initial dimensions of your image output (fig.width and fig.height), which you would need to pre-define in your initial output, but you can specify the ultimate size of the image in your document (out.width). As noted below, however, this is limited to scaling down.
You could also of course leave out the initial directory specification if your files are in the same working directory. Just be aware of operating system differences in specifying the path to the image.
An alternative method is to use Markdown syntax noted by #hermestrismegistus on this post:
![Image Title](./path/to/image.pdf){width=65%}
This can also be collected for multiple images side-by side:
![Image Title](./path/to/image.pdf){width=33%}![Image2 Title](./path/to/image2.pdf){width=33%}![Image3 Title](./path/to/image3.pdf){width=33%}
Edit:
After working more extensively with in-text referencing, I have found that using r chunks and the include_graphics option to be most useful. Also because of the flexibility in terms of image alignment (justification).
As an example:
```{r image-ref-for-in-text, echo = FALSE, message=FALSE, fig.align='center', fig.cap='Some cool caption', out.width='0.75\\linewidth', fig.pos='H'}
knitr::include_graphics("./folder/folder/plot_file_name.pdf")
```
The reference can later be used in-text, for example, Figure \#ref(fig:image-ref-for-in-text) illustrates blah blah.
Some important things to note using this format:
You can only expand PDF images via a code chunk up to the out.width and out.height conditions set in the original .pdf file. So I would recommend setting them slightly on the larger side in your original image (just note that any chart text will scale accordingly).
The in-text reference code (in this case image-ref-for-in-text) CANNOT contain any underscores (_) but can contain dashes (-). You will know if you get this wrong by an error message stating ! Package caption Error: \caption outside float.
To stop your plots drifting to the wrong sections of your document, but in a way that unfortunately will generate some white space, the above example includes fig.pos='H'. Where H refers to "hold" position. The same can be achieved for the former Markdown option by placing a full-stop (period .) immediately after the last curly bracket.
Example:
![Image Title](./path/to/image.pdf){width=75%}.
Unfortunately, this latter option results in some unsightly full-stops. Another reason I prefer the include_graphics option.
Sorry, I found that there is a similar post before:
Add pdf file in Rmarkdown file
Basically, I can use something like below works well for the html output:
<img src="myFirstAlignment2.pdf" alt="some text" width="4200" height="4200">
And something like below works well for the pdf output:
(1)possible solution
\begin{center} <br>
\includegraphics[width=8in]{myFirstAlignment2.pdf} <br>
\end{center}
(2)possible solution
![Alt](myFirstAlignment2.pdf)
The myFirstAlignment2.pdf should be replaced with path\myFirstAlignment2.pdf if the pdf file is not in your working directory.
In relation to the comment of the best answer, there is a way to use the second option, and the output not come out tiny.
Use the following syntax below with the height being a large number. Having text in the brackets is necessary for it to work.
![Alt](./file.pdf){width=100% height=400}
None of the answers outlined worked well for me in terms of sizing the pdf, so adding another answer using the code chunk options for out.height and out.width to control the size:
```{r out.height = "460px", out.width='800px', echo=F}
knitr::include_graphics("./images/imagename.pdf")
```

How do I add a note or text in addition to the caption to a knitr figure for latex output?

I am using knitr to write my thesis and compiling it as a latex document. I have successfully included figures with the appropriately labeled caption; however, in addition to the caption I would like to include additional lines of text directly below the caption and associated with the figure. For example, below the caption I would like to hove: "NOTE: These data are distributed with mu=0 and sd=1" and "SOURCE: These data were randomly generated in R."
EDIT 1 to question: I also need to have a list of figures page with just the caption information included not any of the NOTE or SOURCE information. In addition the caption under the figure must be centered, while the NOTE and SOURCE are left hand justified.
I believe that many publications have figures with notes about the figure or information about the source of the data that is separate from the caption title; so, I believe this question is not just applicable to me.
EDIT 1 to code. Here is a synthesis of the code that #user29020 provided and the link they suggested, as well as the .pdf work around I have assembled from other posts. The advantage of the "pure" knitr method provided by #user29020 is that the plot is beautiful with the text scaled consistently with the body of the text. The disadvantage is a lack of control of the caption information: I would like to center the "Caption" element and left justify the and sub-caption lines and I do not know how to accomplish this; so, if anybody knows how to do this that would be great. The advantage of the pdf work around is that I have greater control over the captions. In addition to not taking full advantage of knitr's ability to create and track figures, the disadvantage is that while the font matches, by using "Ghostscript" the scaling appears a little off and needs to be adjusted in an ad-hoc fashion in the R code.
\documentclass{article}
\usepackage{caption}
\usepackage{tikz}%Draw Graphs
\begin{document}
\listoffigures
\newpage
%THIS IS A SYNTHESIS OF user29020 CODE AND THE LINK THEY PROVIDED IN THEIR COMMENTS
<<cap-setup1,include=FALSE>>=
scap="This is a Caption."
NOTE="NOTE: Here is a note with one linebreak from above."
SOURCE="SOURCE: Here is my source with an extra linebreak to separate it."
EXTRA="{\\tiny EXTRA: Here is smaller text. You could explore more text sizing in \\LaTeX.} And bigger again."
hspace="\\\\\\hspace{\\textwidth}"
cap<- paste(
scap,
hspace,
NOTE,
hspace,
SOURCE,
hspace,
EXTRA)
#
In Figure \ref {fig:fig1}, we see a scatter plot.
<<fig1, echo=FALSE,fig.cap=cap, fig.scap=scap,fig.pos="!h", >>=
r<-rnorm(100)
plot(r)
#
%THIS IS THE PDF WORK AROUND
%Loading R Packages
<<loading,include=FALSE>>=
require(extrafont)
require(graphicx)
font_install("fontcm") #this gets the cm roman family from package extrafont for pdf output in r to match latex
#
<<fig-pdf,echo=FALSE, include=FALSE,fig.cap=paste("This is a Caption"),fig.pos="!h", >>=
Sys.setenv(R_GSCMD="C:/Program Files/gs/gs9.15/bin/gswin64c.exe") #this needs to go inside every r code chunk to call GhostScript for embedding latex font "computer modern roman" (so R font in pdfs matches latex document font)
pdf("tikz-plot-pdf.pdf", family="CM Roman")
set.seed(2015)
r<-rnorm(100)
plot(r)
dev.off()
embed_fonts("tikz-plot-pdf.pdf") #this embeds the pdf font so that when graphicx calls the pdf the fonts from R to latex match
#
\newpage
In Figure \ref{fig:scatter}, we see a scatter plot.
\begin{figure}[!h]
\centering
\includegraphics[width=\textwidth]{tikz-plot-pdf}
\caption{This is also a Caption}\label{fig:scatter}
\begin{minipage}{\textwidth}
NOTE: Here is a note with one linebreak from above.\\
SOURCE: Here is my source with an extra linebreak to separate it.\\
EXTRA:{\tiny EXTRA: Here is smaller text. You could explore more text sizing in \LaTeX.} And bigger again.
\end{minipage}
\end{figure}
\end{document}
I would like to have the "NOTE" and "SOURCE" lines below the caption line, EDIT 1: only the caption included in the \listoffigures and the caption centered, while the NOTE and SOURCE are left justified (like the output from the pdf workaround):
I have not asked a question on this forum before, although I have found many answers, so any meta-feedback on my question EDIT 1: or how I am editing is also appreciated.
Thank You
This answer assumes that multiline captions are sufficient for your purposes. I used your method of passing an R variable to the Knitr fig.cap= argument. This lets us compose the caption ahead of time in other code chunks before use.
The tricks were that A) we need to find out how to add line break to caption without using caption package, and B) know how to pass literal "\" (backslash) characters to the resulting Latex document.
The reference about adding captions suggests adding \\\hspace{\textwidth} to start a new line within the caption (in the Latex file). So, we escape it in the Knitr file like this \\\\\\hspace{\\textwidth}.
Indeed, almost any Latex code you want to end up in the Latex file will have to be escaped this way. When writing your thesis, you'll want to refer to your Figures, no doubt. You can use the Latex references by putting the figure \label into the caption and then using a \ref{} elsewhere.
See the modified version of your file below for multiline captions and figure references:
\documentclass[12pt]{article}%12 Pt font, article document class
\usepackage{caption}
\usepackage{tikz}%Draw Graphs
\begin{document}
<<>>=
x <- paste(
"This is a Caption.",
"\\\\\\hspace{\\textwidth}",
"NOTE: Here is a note with one linebreak from above.",
"\\\\\\hspace{\\textwidth}",
"\\\\\\hspace{\\textwidth}",
"SOURCE: Here is my source with an extra linebreak to separate it.",
"\\\\\\hspace{\\textwidth}",
"{\\tiny EXTRA: Here is smaller text. You could explore more text sizing in \\LaTeX.} And bigger again.",
"\\label{figure:demo-of-multiline-captions}",
"\n" )
cat(x)
#
We can also show the variable "x" in the "asis" formate here:
<<results="asis">>=
cat(x)
#
This text right here (now) is a new paragraph, so it is indented.
Below, in \textbf{Figure~\ref{figure:demo-of-multiline-captions}}, we use the "x" variable in the "fig.cap=" argument to Knitr.
<<fig1, echo=FALSE,fig.cap=x,fig.pos="!h", >>=
r<-rnorm(100)
plot(r)
#
\end{document}
Results give this:

Resources