Rmarkdown, bookdown, texreg and cross-referencing - r

Cross-referencing a table made by texreg in bookdown halfway works. The table is numbered properly but the cross-reference ends up as '??' in the text. A MRE is below. Is there a solution to this, or is there another package that can solve this problem (stargazer has the same problem in bookdown). Using fig.cap has no effect.
Thanks for any help.
---
title: "bookdownTest"
author: "Richard Sherman"
date: "1/9/2020"
output:
bookdown::pdf_document2:
fig_caption: yes
toc: false
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r load libraries, include=FALSE}
library(texreg)
library(bookdown)
```
```{r lm, results='asis', star.symbol = "\\*", center = TRUE}
m1 <- lm(mpg ~ disp + cyl + hp, mtcars)
m2 <- lm(mpg ~ disp + hp, mtcars)
texreg(list(m1, m2), center = TRUE,
caption="Linear model of mpg")
```
Results are in Table \#ref(tab:lm).

texreg() has a label option that lets you set the label, so you can do:
texreg(list(m1, m2), center = TRUE,
caption="Linear model of mpg",
label="tab:lm")
You may have been relying on the automatic table labels described in the bookdown documentation, but that only works when using the knitr::kable() function to generate your table.

Related

R Markdown Presentation: showing one plot in each slide

I have a list of 300 plots and want one PowerPoint slide to show one plot (300 slides). What's the best way to achieve this?
A toy example using the built-in iris dataset to create a list of plots:
purrr::map(names(iris[,-5]), function(col_name){
plot = iris %>%
ggplot(aes(x = !!as.name(col_name))) +
geom_histogram()
return(plot)
})
I hope to create PowerPoint slides with one plot on each slide.
I will be using the iris data set, which is a built-in data set often used to populate example code.
With the following code in a Rmd file:
---
title: "Test_PowerPoint"
author: "KoenV"
date: '2022-06-30'
output: powerpoint_presentation
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
```{r include=FALSE, warning=FALSE, message=FALSE}
library(tidyverse)
library(purrr)
```
```{r, iris, fig.cap="A scatterplot.", echo=FALSE, warning=FALSE, message=FALSE}
## your code
purrr::map(names(iris[,-5]), function(col_name){
plot = iris %>%
ggplot(aes(x = !!as.name(col_name))) +
geom_histogram()
return(plot)
})
```
And after hitting the "knit" button, you will see a PowerPoint presentation appearing, with the following lay-out:
Please let me know, whether this is what you wanted.

How to ref stargazer tables in RMarkdown?

It seems that stargazer tables cannot be referenced in RMarkdown anymore.
I have unsuccessfully tried to implement the workarounds posted on the github page that refer to this problem https://github.com/rstudio/bookdown/issues/175
---
title: "Ref Stargazer Test"
output:
bookdown::html_document2: default
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r results='asis'}
m1 <- lm(mpg ~ cyl + disp, mtcars)
stargazer::stargazer(m1, type = "html", label = "tab:model")
```
Table \#ref(tab:model) should show something on cars.
```{r mytab, results="asis"}
stargazer::stargazer(attitude,
type=ifelse(knitr::is_latex_output(),"latex","html"),
label=knitr::opts_current$get("label"),
title="Stargazer <3 Bookdown")
```
As Table \#ref(tab:mytab) shows, relationships may be hard work but love finds a way.
The referencing does not work as of July 2021 (rmarkdown 2.9, bookdown 0.22, stargazer 5.2.2).
Is there another workaround that works?
I don't know how to achieve this with stargazer. I will note that bookdown cross-references are a pretty recent feature, and that stargazer has not been updated in over 3 years, so issues are bound to arise.
One more modern alternative is the modelsummary package (disclaimer: I am the maintainer). In my biased opinion, this package is more flexible and robust, but YMMV.
Below I paste a minimal example of Rmarkdown document with cross-references. A couple things to note:
modelsummary detects the output format automatically, so you only need to specify LaTeX or HTML in the YAML header at the very top of your Rmarkdown document. No need to use the output argument of modelsummary (but check out the documentation anyway!).
The table label is set by the name of the chunk. Here, it is called "model", so we use tab:model as a cross-reference.
Your table needs a title, otherwise cross-references won't show up consistently.
---
title: "modelsummary cross-reference test"
output:
bookdown::html_document2: default
---
```{r model}
library(modelsummary)
m1 <- lm(mpg ~ cyl + disp, mtcars)
modelsummary(m1, title = "A table title")
```
Table \#ref(tab:model) should show something on cars.
I have found a solution myself that works for LaTeX and HTML.
---
title: "Ref Stargazer Test"
output:
bookdown::html_document2: default
---
Table \#ref(tab:mytable) is the referenced table.
```{r mytable, results='asis', fig.cap="This is my table."}
m1 <- lm(mpg ~ cyl + disp, mtcars)
# Use title caption from fig.cap
tit <- knitr::opts_current$get("fig.cap")
# Adding caption for html output
tit_html <- paste0('<span id="tab:',
knitr::opts_current$get("label"),
'">(#tab:',
knitr::opts_current$get("label"),
')</span>',
tit)
stargazer::stargazer(m1,
label = paste0("tab:", knitr::opts_current$get("label")),
title = ifelse(knitr::is_latex_output(), tit, tit_html),
type = ifelse(knitr::is_latex_output(),"latex","html"),
header = F
)
```
You can now also use the fig.cap argument in the chunk header to write the title you want to have for your table. For referencing, you have to refer to the chunk label (in this case "mytable"). The title argument in stargazer creates the <caption> element, this is why the html title is inserted there.
A simple way of solving this is by adding manually your table's name on stargazer.
label = "tab:table4"
So your code should look something like this:
stargazer(m1, label = "tab:mytable")
And now you will be able to cross reference as usual in Rmarkdown \ref{tab:mytable}

Row height in regression models with jtools in R Markdown

I would like to adjust the row padding in a jtools regression table. I tried set_row_height since I read that the underlying structure is a huxtable. But I'm unsure, and it didn't work.
---
title: "Untitled"
author: "Name"
date: "10 5 2021"
output: html_document
---
## R Markdown
```{r, warning=FALSE, message=FALSE}
mymodel <- lm(mpg ~ ., data=mtcars)
library(tidyverse)
library(jtools)
library(huxtable)
export_summs(mymodel, scale = TRUE) %>%
set_font_size(6) %>% # working in markdown html
set_row_height(., everywhere, 0.1) # not working in html
```
It looks fine in RStudio, but uses extensive row space in Markdown. set_font_size is working, but set_row_height not.
Finally, row height adjustment worked with set_tb_padding. I cannot replicate why it didn't worked in the first place. set_row_height requires CSS/LaTeX values, i.e. set_row_height("4cm"). I cannot reduce row height to a resonable size but can increase row height.
title: "Jtools and Huxtable"
author: "Name"
date: "10 5 2021"
output: html_document
---
## R Markdown
```{r, warning=FALSE, message=FALSE}
mymodel <- lm(mpg ~ ., data=mtcars)
library(tidyverse)
library(jtools)
library(huxtable)
export_summs(mymodel, scale = TRUE) %>%
set_font_size(10) %>%
set_tb_padding(1)
```

How to show significance stars in R Markdown (rmarkdown) html output notes?

I want to show regression outputs in HTML documents using R Markdown. I tried the texreg and stargazerpackages. My problem is now, that in the notes I can't bring the significance stars to life. Due to automatic generation it seems I can't escape them. I've been puzzling around with this and this but with no success. What am I missing? Thanks a lot!!
Here's some code:
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r data}
library(car)
lm1 <- lm(prestige ~ income + education, data=Duncan)
```
## with STARGAZER
```{r table1, results = "asis", message=FALSE}
library(stargazer)
stargazer(lm1, type="html", notes="stargazer html 1") # nothing
stargazer(lm1, type="html", notes="stargazer html 2", star.char = "\\*") # nothing, even gone in table
```
## with TEXREG
```{r table2, results = "asis", message=FALSE}
library(texreg)
htmlreg(lm1, custom.note="%stars. htmlreg") # nothing
htmlreg(lm1, custom.note="%stars. htmlreg", star.symbol = "\\*") # still nothing!
```
Note: Question was a former sub-question I have now splitted.
Use the HTML entity for the asterisk:
star.symbol='*'
See http://www.ascii.cl/htmlcodes.htm.
You could also add the "legend" manually:
stargazer(lm1, type="html", notes = "<em>*p<0.1;**p<0.05;***p<0.01</em>", notes.append = F)

Print RMarkdown captions from a loop

I am creating a series of plots from within a loop in an RMarkdown document, then knitting this to a PDF. I can do this without any problem, but I would like the caption to reflect the change between each plot. A MWE is shown below:
---
title: "Caption loop"
output: pdf_document
---
```{r, echo=FALSE}
library(tidyverse)
p <-
map(names(mtcars), ~ggplot(mtcars) +
geom_point(aes_string(x = 'mpg', y = .))) %>%
set_names(names(mtcars))
```
```{r loops, fig.cap=paste(for(i in seq_along(p)) print(names(p)[[i]])), echo=FALSE}
for(i in seq_along(p)) p[[i]] %>% print
```
I have made a first attempt at capturing the plots and storing in a variable p, and trying to use that to generate the captions, but this isn't working. I haven't found too much about this on SO, despite this surely being something many people would need to do. I did find this question, but it looks so complicated that I was wondering if there is a clear and simple solution that I am missing.
I wondered if it has something to do with eval.after, as with this question, but that does not involve plots generated within a loop.
many thanks for your help!
It seems that knitr is smart enough to do the task automatically. By adding names(mtcars) to the figure caption, knitr iterates through these in turn to produce the correct caption. The only problem now is how to stop all of the list indexes from printing in the document...
---
title: "Caption loop"
output: pdf_document
---
```{r loops, fig.cap=paste("Graph of mpg vs.", names(mtcars)), message=FALSE, echo=FALSE, warning=FALSE}
library(tidyverse)
map(
names(mtcars),
~ ggplot(mtcars) +
geom_point(aes_string(x = 'mpg', y = .))
)
```
In case this might be useful to somebody. Here is an adaptation of Jonny's solution for captions without printing list indices. This can be achieved by using purrr::walk instead of purrr::map. Also included is a latex fig label and text that references each plot.
---
title: "Loop figures with captions"
output:
pdf_document
---
```{r loops, fig.cap=paste(sprintf("\\label{%s}", names(mtcars)), "Graph of mpg vs.", names(mtcars)),results='asis', message=FALSE, echo=FALSE, warning=FALSE}
library(tidyverse)
library(stringi)
walk(names(mtcars),
~{
p <- ggplot(mtcars) +
geom_point(aes_string(x = 'mpg', y = .))
#print plot
cat('\n\n')
print(p)
#print text with refernce to plot
cat('\n\n')
cat(sprintf("Figure \\ref{%s} is a Graph of mpg vs. %s. %s \n\n", ., .,
stri_rand_lipsum(1)))
cat("\\clearpage")
})
```

Resources