Avoiding repetitive LaTeX codes in R Markdown

Hi!

I am preparing a PDF, which has lots of figures and tables. I wanted to add captions to all of them automatically, but was not successful, as you can see here.

As an workaround, I am using the caption package to add caption to each one of them separately, like the following.

---
title: "Example"
date: "28 April 2018"
output: pdf_document
header-includes:
- \usepackage{caption}
---

```{r include = FALSE}
x <- rnorm(10)
pdf("first.pdf")
plot(x)
dev.off()
y <- rcauchy(10)
pdf("second.pdf")
plot(y)
dev.off()
z <- runif(10)
pdf("third.pdf")
plot(z)
dev.off()
```

Bla...Bla...Bla

\includegraphics{first.pdf}
\captionof{figure}{normal}

Bla...Bla...Bla

\begin{center}
\begin{tabular}{r}
\hline
x\\
\hline
0.0017384\\
\hline
0.0191490\\
\hline
0.0661849\\
\hline
0.0341861\\
\hline
0.0044048\\
\hline
0.0285763\\
\hline
0.0118869\\
\hline
0.0358421\\
\hline
0.0262538\\
\hline
0.0065091\\
\hline
0.0185175\\
\hline
0.0126261\\
\hline
0.0022572\\
\hline
0.0094838\\
\hline
0.0734565\\
\hline
0.0248889\\
\hline
0.0122629\\
\hline
0.0047293\\
\hline
0.1004818\\
\hline
0.0067478\\
\hline
\end{tabular}
\captionof{table}{shapiro}
\end{center}

Bla...Bla...Bla

\includegraphics{second.pdf}
\captionof{figure}{}

Bla...Bla...Bla

\includegraphics{third.pdf}
\captionof{figure}{uniform}

Bla...Bla...Bla

\begin{center}
\begin{tabular}{r|r|r|r|r|r|r|r|r|r}
\hline
-1.5569048 & -1.2940827 & 1.7106294 & 0.1723490 & -2.1006933 & -0.8110029 & 1.3568960 & 0.3838090 & -0.0664289 & 1.0860245\\
\hline
-0.0006826 & 0.0738968 & 0.6309370 & 0.9382452 & -0.8759342 & 1.0677394 & -0.1363563 & 1.7599148 & -0.5858252 & 2.3932724\\
\hline
0.7751907 & 1.3758625 & -0.4498818 & -0.6188443 & 0.1046838 & 1.3741381 & -0.0546395 & 0.2451491 & -1.2914554 & 0.9379431\\
\hline
-0.1828093 & 0.4569917 & -0.4182240 & -0.3978720 & 0.6531548 & -1.2027918 & -0.6495577 & 0.4871754 & -0.9405698 & -1.6928845\\
\hline
1.1212768 & 1.7779455 & 0.9141339 & 1.5619030 & -0.1583376 & 0.8200586 & 1.2796174 & -0.4995602 & -1.5686963 & -0.2077684\\
\hline
\end{tabular}
\captionof{table}{}
\end{center}

Bla...Bla...Bla

\begin{center}
\begin{tabular}{r}
\hline
x\\
\hline
0.0023577\\
\hline
0.1127297\\
\hline
0.0023940\\
\hline
0.0053369\\
\hline
0.0279039\\
\hline
0.3645155\\
\hline
0.0052540\\
\hline
0.0408357\\
\hline
0.0220720\\
\hline
0.0026888\\
\hline
0.0036803\\
\hline
0.0033165\\
\hline
0.0931782\\
\hline
0.3248195\\
\hline
0.0003181\\
\hline
0.1183903\\
\hline
0.4139152\\
\hline
0.0010397\\
\hline
0.0028948\\
\hline
0.3686759\\
\hline
\end{tabular}
\captionof{table}{kolmogorov}
\end{center}

The above yields Example.pdf (80.8 KB).

But in this way, for every figure, first I need to save the graph separately and then use

\begin{center}
\includegraphics{some_filename.pdf}
\captionof{figure}{some_text}
\end{center}

Obviously, the best solution would be to automate captions as the R codes generate graphs, but as that failed, I would like to call something of the sort caption(type, text) within the code chunk and it will create a caption named text (possibly blank) starting with "Figure k" or "Table l" etc.

Is it possible to achieve this?

Thanks.

1 Like

Another approach to save all that typing could be to use snippets. I don't use RStudio, so I don't know how snippets work in it, but in the system I use, this would be very easy to implement. I imagine that RStudio snippets have similar capabilities. Once you have created a snippet, you call it with a few key strokes and "tab" (or other key) from field to field that you can customize. Adding repetitive chunks of code which follow a pattern becomes really quick easy.

To be honest with you, though I like your suggestion very much, I have never ever used snippets. I know that there's an option, but ... I haven't used it ever. I don't know how to create one, but obviously I can find some guides online.

But surely there will be an elegant way out? You just can't make snippets for every possible cases, isn't it?

I really wish that there's an simple automated way to create captions, something more customizable than fig.cap.

Have a look at them sometime :slight_smile: Again, I use another system and the RStudio snippets might be a little different. But I live with snippets :smile:

Again, someone familiar with RStudio snippets would be better than me here, but in the system I use, I can create basic snippets that expand to a fixed expression, or more fancy ones that allow me to jump from place to place where I can add the customized sections. So I can cover all the cases with a single snippet, as long as all the cases follow the same pattern.

Here is one:

RStudio snippets do work, as I expected, in the same way as the ones I am familiar with. It is pretty simple to create snippets, really. And once you get familiar with them, you'll wonder how you could live without them :smile:

I'm not sure I have a clear picture of how you'd want this to work, but do you know about knitr chunk and output hooks?

It's not a readymade solution to your specific problem, but it's maybe a tool with which one might be created?

(That said, I fear there's a serious risk that the classic xkcd comic applies here, so I also agree with @prosoitos that clever use of snippets will ease the pain a lot!)

1 Like

:laughing:

I have no idea what you are talking about :thinking:

:wink:

I can't imagine doing anything like that myself, of course... no no no... :innocent:

1 Like

:joy:

Of course not. Same here.

image

*(apologies for the pie chart on an R forum...)

1 Like

Thanks for the links, @prosoitos and @jcblum. I'll go through these and update after I succeed in modifying for my problem.

Cheers, Anirban

2 Likes

I had a chance to take a closer look at your first thread on this problem, and I have to say I do think it's worth giving the captioner package another try. I think the key is to do as the package author recommends in the vignette and NOT try to use the fig.cap chunk option at all, but simply call your captioner function as inline code, like `r fig_caption("plot-name")` immediately after a code chunk with a figure. I realize this doesn't solve the issue of chunks with more than one plot. But... why not have each plot in its own chunk?

FWIW, the development version of captioner also now has auto-integration with knitr chunk hooks.

Anyway, you'll figure out what works best for you (no pun intended :weary:), but if you do sort out a solution you're happy with, I hope you post back here about it! Good luck!

Sorry for being so late. It was a really busy week. I could not understand how to use the hooks effectively for my requirement, though I admit that I went through the materials rather hastily. I decided finally that I will use use captioner for captions for figures (which works fine except that I can't set the aligning), and either the same for tables, or the combination of kable and default markdown format. The default format and kable correctly track the total number of tables already present, but captioner can't. It helped indirecctly though, if one wants to start the counter once again for diffferent sections (I don't know any alternative for that). I tried the following:

---
title: "Example"
date: "28 April 2018"
output: pdf_document
---

```{r}
set.seed(1703)
fig_cap <- captioner::captioner()
tab_cap <- captioner::captioner("Table")
```

Bla...Bla...Bla

```{r}
x <- rnorm(10)
plot(x)
```

`r fig_cap(1, display = "cite")`

Bla...Bla...Bla

```{r}
y <- rcauchy(10)
plot(y)
```

`r fig_cap(2, caption = "this should be shown only figure 2", display = "full")`

Bla...Bla...Bla

```{r}
z <- runif(10)
plot(z)
```

`r fig_cap(3, display = "num")`

Bla Bla Bla

|          x|
|----------:|
|  0.5034229|
|  0.8314031|
|  0.3090216|
| -0.9383080|
|  0.7897246|
| -0.9350987|
|  0.7087313|
|  2.5481824|
|  1.3814061|
|  1.8230985|

`r tab_cap(1, "captioner table one, actually one")`

Bla Bla Bla

`r knitr::kable(cbind(w = sample(100, 10)), caption = "knitrs table one, actually two")`

Bla...Bla...Bla

|           y|
|-----------:|
|  -0.2705723|
|  -0.2776932|
|  -0.2327131|
| -11.7280841|
|  -0.7160195|
|   8.5216133|
|  -0.5755096|
|  -9.6421121|
|   2.7299350|
|   1.5299834|

Table: default table one, actually three

Bla...Bla...Bla

|         z|
|---------:|
| 0.6082432|
| 0.5308447|
| 0.1027917|
| 0.9105425|
| 0.3845761|
| 0.0170002|
| 0.3300129|
| 0.0526674|
| 0.1263493|
| 0.6596739|

`r tab_cap(2, "captioner table two, actually four")`

Bla...Bla...Bla

|          w|
|----------:|
| -0.7160195|
|  0.7897246|
|  1.3814061|
|  0.5034229|
|  0.1027917|
| -9.6421121|
|  0.7087313|
|  8.5216133|
| -0.2776932|
|  0.9105425|

Table: default table one, actually five

Bla...Bla...Bla

It creates the following Captions.pdf (131.4 KB).

If there's a better solution, please let me know.

Thanks.

3 Likes