Caption above figure in html Rmarkdown
Asked Answered
P

4

9

Is it possible to move the caption above my figure when knitting to HTML in RMarkdown? It seems that it is possible in PDF, ie when knitting to PDF, but I can't figure out how to replicate this for HTML. I am using bookdown to number figures.

When I run something like this:

```{r fig.cap= "caption"}
df <- data.frame(letter = letters[1:5], value = 1)

ggplot(df, aes(as(factor(1), value, fill = letters))) +
  geom_bar(stat = "identity")

```

the caption is displayed at the bottom of the figure, but I would like to display it above the figure.

Phylloxera answered 10/7, 2019 at 21:40 Comment(3)
This seems reasonable to want the option of captions above. The convention of below for figures but above for tables need not be enforced! It was discussed as an issue at bookdown github, but closed without resolution.Lorollas
Code here seems to work for me. #22336042Khan
Thanks @dyrland, though the figure numbering that is provided with bookdown is suppressed by that solution.Lorollas
P
11

For HTML output, you may set the chunk option fig.topcaption = TRUE to place captions above figures. Below is a minimal example (it works for both html_document and bookdown's HTML output formats):

---
title: "Reprex"
output:
  html_document: null
  bookdown::html_document2: null
---

```{r, fig.cap='A caption.', fig.topcaption=TRUE}
plot(cars)
```

Caption above the figure

Prine answered 3/3, 2020 at 21:56 Comment(4)
That was much easier than I imagined! Unfortunately the use of ggplotly to turn a ggplot() into a plotly object appears to send the title back to the bottom, though numbering is retained. I'll try and modify the example in my answer to show this.Lorollas
See lower section of answer here with an example that shows that the caption reverts to the bottom with a plotly object.Lorollas
Solution for plotly object with some css hereLorollas
Is the fig.topcaption hook documented anywhere?Ear
D
4

You can do that, but if you set echo = TRUE, the caption will appear above the code...

---
title: "Untitled"
author: "Stéphane Laurent"
date: "29 février 2020"
output: html_document
---

```{r setup, include=FALSE}
knitr::knit_hooks$set(htmlcap = function(before, options, envir) {
  if(before) {
    paste('<p class="caption">', options$htmlcap, "</p>",sep="")
  }
})
```

```{r, echo = FALSE, htmlcap="Hello Dolly"}
library(ggplot2)
ggplot(diamonds,aes(price,carat)) + geom_point()
```
Decennary answered 29/2, 2020 at 13:7 Comment(1)
The answer proposed by Stéphane, and the answer from the link suggested by dyrland, both move the caption above the figure. The downside of Stephane's solution (as mentioned) is that it appears above the code if echo=TRUE. A bigger downside is that with both solutions the automatic numbering provided by bookdown appears to be supressed. As it is not my question, I think I will make an answer that shows this.Lorollas
L
3

This is not a successful answer, but code output shows that the choice of a bookdown format, that would otherwise number the figure, is suppressed by inclusion of the solution proposed by Stéphane, or, as below, solution from the link suggested by dyrland.

---
title: "Untitled"
author: "Internet"
date: "29 février 2020"
output:
  bookdown::html_document2
---

```{r setup2}
#https://mcmap.net/q/1171736/-knitr-figure-captions-above 
library(knitr)
knit_hooks$set(plot = function(x, options) {
  paste('<figure><figcaption>', options$fig.cap, '</figcaption><img src="',
        opts_knit$get('base.url'), paste(x, collapse = '.'),
        '"></figure>',
        sep = '')
}) #comment out to restore numbering

library(ggplot2)
```

```{r, echo = TRUE, fig.cap="Hello Dolly"}
ggplot(diamonds,aes(price,carat)) + geom_point()
```

Can a solution include both the numbering and the caption at the top?

N.B Author of the original question did mention bookdown, but did not provide a full working example to demonstrate this. Happy to edit original question if other think that would be more useful.

EDIT Yihui has shown in his answer that there is an easy option with fig.topcaption=TRUE - Thanks! Unfortunately that caption, though it retains correct numbering, is still pushed to the bottom (in the case of plotly figures). Example below:

---
title: "Untitled"
author: "Internet"
date: "29 février 2020"
output:
  bookdown::html_document2
---

```{r setup, message=FALSE, echo=FALSE}

library(knitr)
library(ggplot2)
library(plotly)

```

Here is a ggplot object with caption at the top as desired.


```{r, fig.cap="Hello ggplot", fig.topcaption=TRUE, message=FALSE, echo=FALSE}
ggplot(diamonds,aes(price,carat)) + geom_point()
```

Here is the previous ggplot converted to a plotly object with caption reverting to the bottom.


```{r, fig.cap="Hello plotly", fig.topcaption=TRUE, message=FALSE, echo=FALSE}
my_ggplot <- ggplot(diamonds,aes(price,carat)) + geom_point()
ggplotly(my_ggplot)
```

Caption reverts to bottom even if plotly object is not created from ggplot object

```{r, fig.cap="Hello plotly2", fig.topcaption=TRUE, message=FALSE, echo=FALSE}
plot_ly(
  x=c(1,2,3),
  y=c(5,6,7),
  type='scatter',
  mode='lines')
```

EDIT 2 Plotly caption location issue solved with css here

Lorollas answered 1/3, 2020 at 22:40 Comment(0)
K
2

Hardcoding a function is function is never my preferred option, but it works (Create another function for Tables.) (Source code here: R Markdown HTML Number Figures)

Now, to figure out how to reference these...

---
title: "Untitled"
author: "Internet"
date: "29 fevrier 2020"
output:
  bookdown::html_document2
---

```{r setup2}
#https://mcmap.net/q/1171736/-knitr-figure-captions-above 
library(knitr)
library(ggplot2)

capFigNo <- 1
capFig <- function(x){
      x <- paste0("Figure ",capFigNo,": ",x)
    capFigNo <<- capFigNo + 1
    x
}


knit_hooks$set(plot = function(x, options) {
  paste('<figure><figcaption>',
        options$fig.cap,
        '</figcaption><img src="',
        opts_knit$get('base.url'),
        paste(x, collapse = '.'),
        '"></figure>',
        sep = '')
}) #comment out to restore numbering

```


```{r echo = TRUE, fig.cap=capFig("Hello Dolly")}
#the trick is to wrap your caption in your number prefixing function.
ggplot(diamonds,aes(price,carat)) + geom_point()
```

```{r echo = TRUE, fig.cap=capFig("Hello Dolly2")}
ggplot(diamonds,aes(price,carat)) + geom_point()    
```
Khan answered 2/3, 2020 at 22:23 Comment(3)
Thanks @dyrland. That will work, though for numbering within chapters I'd have to modify code to number figures (eg in chapter 5 we'd have 5.1, 5.2 possibly to 5.11). I am hoping that someone more capable than I can work a general solution into the github issue which is latex oriented and now closed. Though maybe it needs a new issue to specify a html solution - thoughts?Lorollas
The real answer is to find where the numbering is actually stored (options$something or opts_knit$get("something") and put that in front of options$fig.cap. I just haven't been able to find where it is stored.Khan
To number within a chapter add ChapterNo <- 5 (i.e. for chapter 5), and edit second line of capFig function to this x <- paste0("Figure ",ChapterNo,".",capFigNo,": ",x). Still hoping for a more general solution though!Lorollas

© 2022 - 2024 — McMap. All rights reserved.