Caption above figure in html Rmarkdown - r

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.

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)
```

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()
```

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://stackoverflow.com/a/26743812/4927395
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

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://stackoverflow.com/a/26743812/4927395
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()
```

Related

Is it possible to change the fig.cap chunk option within knitr?

I'd like to change the fig.cap chunk option within a chunk for a knitr document. I tend to write a lot of reporting code that looks like the following to take a plot out of a tibble and use the associated caption with it.
```{r fig, fig.cap=d_plot$caption}
d_plot <- [load the plotting tibble from prior work]
knit_print(d_plot$figure[[1]])
```
Something similar to what I'd like to do is the following, but where the caption actually shows up. And, better yet would be if it would modify fig.cap and fig.scap with the possibility of having multiple knit_print() calls with multiple sets of figures.
---
title: "Untitled"
author: "William Denney"
date: '2022-04-19'
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo=FALSE, warning=FALSE, error=FALSE)
library(tidyverse)
library(knitr)
```
# Test
```{r functions, include=FALSE}
knit_print.fig_n_cap <- function(x) {
lapply(x$figure, knit_print)
opts_chunk$set(fig.cap=x$caption)
}
as_fig_n_cap <- function(x) {
stopifnot(is.data.frame(x))
stopifnot("figure" %in% names(x))
stopifnot("caption" %in% names(x))
class(x) <- c("fig_n_cap", class(x))
x
}
p <- ggplot(data.frame(x=1:3, y=1:3), aes(x=x, y=y)) + geom_line()
d <- as_fig_n_cap(tibble(figure=list(p), caption="My caption"))
```
```{r}
knit_print(d)
```

Rotate table pdf output from Markdown

I want to rotate table output by 90 degrees on pdf. I am using markdown to generate a report and kable to display the tables in a loop. If possible, I would like to continue using kable since there are lot of other things which are dependent on it that I haven't included in this MWE.
This is a simple example using iris dataset. I tried using landscape function from this post Rotate a table from R markdown in pdf
---
output: pdf_document
header-includes:
\usepackage{lscape}
\usepackage{pdfpages}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
Report page -
```{r results='asis'}
library(knitr)
library(kableExtra)
for (i in 1:3) {
print(landscape(kable_styling(
kable(iris[i:(i+5), ], format = "latex", align = "c", booktabs = TRUE,
longtable = TRUE, row.names = FALSE), latex_options = c("striped"), full_width = T)))
}
```
But this only rotates the page number keeping the table as it is.
I am actually looking for a solution which provides me the output in this way -
To clarify, all the pages with table data in it (3 for this example) should be rotated whereas rest of them should remain as it is. Also, I need longtable = TRUE in kable since in my actual example I am printing lot of rows.
Use package rotating
I added a simple example for you.
---
title: "test"
header-includes: \usepackage[figuresright]{rotating}
#or \usepackage[figuresleft]{rotating}
output:
pdf_document:
latex_engine: xelatex
---
```{r setup, include = FALSE}
library(flextable)
ft <- flextable(head(mtcars))
```
\begin{sidewaysfigure}
`r ft`
\end{sidewaysfigure}
```
Further you can modify it for your tasks ;)
I found another way using rotatebox.
---
output: pdf_document
header-includes:
\usepackage{lscape}
\usepackage{pdfpages}
\usepackage{graphicx}
\usepackage[figuresright]{rotating}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
Report page -
```{r results='asis', warning=FALSE, message=FALSE}
library(knitr)
library(kableExtra)
for (i in 1:3) {
cat('\\rotatebox{90}{')
print(kable(iris[i:(i+5), ], format = "latex", align = "c", booktabs = TRUE,
row.names = FALSE))
cat('}')
cat("\n\\newpage\n")
}
```

Format Captions in R Markdown for Word Output

Default R Markdown captions in Word appear as:
Figure 1: Figure Title
Table 1: Table Title
I would like to format my captions so that the Figure 1/Table 1 is bold and the title is italic on the next line. This is the APA style of captions:
Figure 1
Figure Title
I have been trying to figure out an easy way to do this, but can't seem to find a solution. (If figure captions can be above figure, rather than below, that would also be great!). Here is a minimal reprex:
---
title: "Untitled"
author: "Test"
date: "11/8/2020"
output:
bookdown::word_document2: default
---
{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(flextable)
{r table, tab.cap="Descriptives", echo=FALSE, message=FALSE, warning=FALSE}
psych::describe(cars) %>%
as.data.frame() %>%
flextable() %>%
set_table_properties(layout = "autofit", width = 1)
{r fig, fig.cap="Pressure Figure", echo=FALSE, message=FALSE, warning=FALSE}
plot(pressure)
For tables you can do it with officedown, officer and flextable packages, styling in reference_doxc, and by taking the advantage of "\n\n" for tables.
In yaml in the pre argument you set up a prefix for every table and a separator between the number and the title itself.
---
title: "Untitled"
author: "Test"
date: "11/8/2020"
output:
officedown::rdocx_document:
tables:
caption:
pre: 'Table '
sep: ''
---
With
tab.cap.fp_text = officer::fp_text_lite()
you can define the formatting of the caption prefix. In APA style it would be bold without italics, preferrably configured in the global knitr options, e.g.
knitr::opts_chunk$set(tab.cap.fp_text = officer::fp_text_lite(italic = FALSE, bold = TRUE))
And you add
"\n\n"
to the table caption to produce a new line
{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, tab.cap.fp_text = officer::fp_text_lite(italic = FALSE, bold = TRUE))
library(tidyverse)
library(flextable)
{r table, tab.cap="\n\nDescriptives", echo=FALSE, message=FALSE, warning=FALSE}
psych::describe(cars) %>%
as.data.frame() %>%
flextable() %>%
set_table_properties(layout = "autofit", width = 1)
The last thing is to create a reference_doxc in which you add italics to the table caption style. The caption prefix is not affected, as you control it with the knitr options.

Is there a way to unify the numbering of tables caption in r markdown to html in r via `kable()` and `htmltable()`?

When I want to print some tables in html report from knitr, sometime I use knitr::kable(), and other times I use htmltable::htmltable.
When I use bookdown::html_document2 in the YAML numbering of tables from kable is automatic. However, it is not for htmltable, and I need to use options(table_counter = TRUE), which generates another numbering mechanism. Is there a way to unify it?
Example:
---
title: "Untitled"
author: "Guilherme"
date: "10/26/2020"
output:
bookdown::html_document2
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
options(table_counter = TRUE)
```
```{r cars}
library(htmlTable)
htmlTable(mtcars[1:5,1:5],
caption = "XX")
```
```{r}
htmlTable(mtcars[1:5,1:5],
caption = "XX")
```
```{r}
library(knitr)
kable(mtcars[1:5,1:5],
caption = "XX")
```
Outputs:
Thanks!

How to use LaTeX Code in R Chunk in R-Markdown?

I am currently writing on a report with rmarkdown and therefore I want to create sections inside a r code chunk. I figured out that this is possible with the help of cat() and results="asis". My problem with this solution is, that my R code results and code isn't properly displayed as usual.
For example
---
title: "test"
output: pdf_document
---
```{r, results='asis'}
for (i in 1:10) {
cat("\\section{Part:", i, "}")
summary(X)
$\alpha = `r X[1,i]`$
}
```
pretty much does the trick, but here there are still two problems:
the R output for summary() is displayed very strange because I guess it`s interpreted as LaTeX code
I can't use LaTeX formulas in this enviroment, so if I want every section to end with a equation, which also might use a R variable, this is not possible
Does somebody know a solution for some of these problems, or is there even a workaround to create sections within a loop and to have R code, R output and LaTeX formulas in this section? Or maybe at least one of those things?
I am very thankful for every kind of advice
You can do what you are after inline without relying as much on code blocks.
As a minimal example.
---
title: "test"
output: pdf_document
---
```{r sect1_prep, include=FALSE}
i <- 1
```
\section{`r paste0("Part: ", i)`}
```{r sect1_body}
summary(mtcars[, i])
```
$\alpha = `r mtcars[1, i]`$
```{r sect2_prep, include=FALSE}
i <- i + 1
```
\section{`r paste0("Part: ", i)`}
```{r sect2_body}
summary(mtcars[, i])
```
$\alpha = `r mtcars[1, i]`$
Produces...
If you really want to have a section factory, you could consider pander.
---
title: "test"
output: pdf_document
---
```{r setup, include=FALSE}
library(pander)
panderOptions('knitr.auto.asis', FALSE)
```
```{r, results='asis', echo=FALSE}
empty <- lapply(1:10, function(x) {
pandoc.header(paste0("Part: ", x), level = 2)
pander(summary(mtcars[, x]))
pander(paste0("$\\alpha = ", mtcars[1, x], "$\n"))
})
```
which produces...
remove summary table format example
---
title: "test"
output: pdf_document
---
```{r setup, include=FALSE}
library(pander)
panderOptions('knitr.auto.asis', FALSE)
```
```{r, results='asis', echo=FALSE}
content <- lapply(1:10, function(x) {
head <- pandoc.header.return(paste0("Part: ", x), level = 2)
body1 <- pandoc.verbatim.return(attr(summary(mtcars[, x]), "names"))
body2 <- pandoc.verbatim.return(summary(mtcars[, x]))
eqn <- pander_return(paste0("$\\alpha = ", mtcars[1, x], "$"))
return(list(head = head, body1 = body1, body2 = body2, eqn = eqn))
})
writeLines(unlist(content), sep = "\n\n")
```

Resources