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

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)

Related

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}

Rmarkdown, bookdown, texreg and cross-referencing

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.

P-values significance not showed in stargazer html regression table

I am having trouble with the Notes significance (asterisks) not appearing when using stargazer to format html tables. The result is ok when using latex.
Here is my source file "teste.Rmd"
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r data}
#some data
set.seed(123)
X = rnorm(500,10,3)
Y = 10+ 3*I(X^1.2) + rnorm(500)
# models
m1 = lm(Y~X)
m2 = lm(Y~X+I(X^2))
```
```{r res,warning=FALSE,message=FALSE,results='asis'}
library(stargazer)
stargazer(m1,m2,type = 'html',title = 'Models' )
```
The result is below
The same with latex produces this
As you can see the asterisks in Notes are formatted correctly with latex but not with html option. How to get the same behavior with html?
Maybe it is a bug as #jaySf said in the comments to the original question. But based on #tmfmnk's answer and htmltools package I ended with a workaround. This is the updated relevant part of the source file.
```{r res,warning=FALSE,message=FALSE,results='hide'}
library(stargazer)
stargazer(m1,m2,type = 'html',title = 'Models', out = "table1.html")
```
```{r, echo=FALSE}
htmltools::includeHTML("table1.html")
```
Now I got the desired result
Try adding customized notes using notes and notes.append parameters as follows:
stargazer(m1,m2,type='html',notes="<span>***</span>: p<0.01; <span>**</span>: p<0.05; <span>*</span>: p<0.1",notes.append=F)
I originally thought that using backslash to escape * will work, e.g. notes="\\*\\*\\*: p<0.01; \\*\\*: p<0.05; \\*: p<0.1". Unfortunately, it doesn't. I also tried to use the HTML code of *, i.e. *, e.g. notes="***: p<0.01; **: p<0.05; *: p<0.1". Still it doesn't work.
However, surrounding * with an HTML tag works. It doesn't have to be <span></span>. I tried <b></b>, etc. and they worked.
When exported through out it is working fine:
stargazer(m1,m2,type = 'html',
title = 'Models',
out = "/path/table.html")

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

Using knitr to produce complex dynamic documents

The minimal reproducible example (RE) below is my attempt to figure out how can I use knitr for generating complex dynamic documents, where "complex" here refers not to the document's elements and their layout, but to non-linear logic of the underlying R code chunks. While the provided RE and its results show that a solution, based on such approach might work well, I would like to know: 1) is this a correct approach of using knitr for such situations; 2) are there any optimizations that can be made to improve the approach; 3) what are alternative approaches, which could decrease the granularity of code chunks.
EDA source code (file "reEDA.R"):
## #knitr CleanEnv
rm(list = ls(all.names = TRUE))
## #knitr LoadPackages
library(psych)
library(ggplot2)
## #knitr PrepareData
set.seed(100) # for reproducibility
data(diamonds, package='ggplot2') # use built-in data
## #knitr PerformEDA
generatePlot <- function (df, colName) {
df <- df
df$var <- df[[colName]]
g <- ggplot(data.frame(df)) +
scale_fill_continuous("Density", low="#56B1F7", high="#132B43") +
scale_x_log10("Diamond Price [log10]") +
scale_y_continuous("Density") +
geom_histogram(aes(x = var, y = ..density..,
fill = ..density..),
binwidth = 0.01)
return (g)
}
performEDA <- function (data) {
d_var <- paste0("d_", deparse(substitute(data)))
assign(d_var, describe(data), envir = .GlobalEnv)
for (colName in names(data)) {
if (is.numeric(data[[colName]]) || is.factor(data[[colName]])) {
t_var <- paste0("t_", colName)
assign(t_var, summary(data[[colName]]), envir = .GlobalEnv)
g_var <- paste0("g_", colName)
assign(g_var, generatePlot(data, colName), envir = .GlobalEnv)
}
}
}
performEDA(diamonds)
EDA report R Markdown document (file "reEDA.Rmd"):
```{r KnitrSetup, echo=FALSE, include=FALSE}
library(knitr)
opts_knit$set(progress = TRUE, verbose = TRUE)
opts_chunk$set(
echo = FALSE,
include = FALSE,
tidy = FALSE,
warning = FALSE,
comment=NA
)
```
```{r ReadChunksEDA, cache=FALSE}
read_chunk('reEDA.R')
```
```{r CleanEnv}
```
```{r LoadPackages}
```
```{r PrepareData}
```
Narrative: Data description
```{r PerformEDA}
```
Narrative: Intro to EDA results
Let's look at summary descriptive statistics for our dataset
```{r DescriptiveDataset, include=TRUE}
print(d_diamonds)
```
Now, let's examine each variable of interest individually.
Varible Price is ... Decriptive statistics for 'Price':
```{r DescriptivePrice, include=TRUE}
print(t_price)
```
Finally, let's examine price distribution across the dataset visually:
```{r VisualPrice, include=TRUE, fig.align='center'}
print(g_price)
```
The result can be found here:
http://rpubs.com/abrpubs/eda1
I don't understand what's non-linear about this code; perhaps because the example (thanks for that by the way) is small enough to demonstrate the code but not large enough to demonstrate the concern.
In particular, I don't understand the reason for the performEDA function. Why not put that functionality into the markdown? It would seem to be simpler and clearer to read. (This is untested...)
Let's look at summary descriptive statistics for our dataset
```{r DescriptiveDataset, include=TRUE}
print(describe(diamonds))
```
Now, let's examine each variable of interest individually.
Varible Price is ... Decriptive statistics for 'Price':
```{r DescriptivePrice, include=TRUE}
print(summary(data[["Price"]]))
```
Finally, let's examine price distribution across the dataset visually:
```{r VisualPrice, include=TRUE, fig.align='center'}
print(generatePlot(data, "Price"))
```
It looked like you were going to show the plots for all the variables; are you perhaps looking to loop there?
Also, this wouldn't change the functionality, but it would be much more within the R idiom to have performEDA return a list with the things it had created, rather than assigning into the global environment. It took me a while to figure out what the code did as those new variables didn't seem to be defined anywhere.

Resources