1

I'm using this tutorial to perform a linear regression. Is there a way to add the summary (results) of the linear model to the plot in order to save it as a pdf.

This is the code:

scatter.smooth(x=cars$speed, y=cars$dist, main="Dist ~ Speed")  # scatterplot


linearMod <- lm(dist ~ speed, data=cars)  # build linear regression model on full data
print(linearMod)

#> Call:
#> lm(formula = dist ~ speed, data = cars)
#> 
#> Coefficients:
#> (Intercept)        speed  
#>     -17.579        3.932





summary(linearMod)  # model summary
#> Call:
#> lm(formula = dist ~ speed, data = cars)
#> 
#> Residuals:
#>     Min      1Q  Median      3Q     Max 
#> -29.069  -9.525  -2.272   9.215  43.201 
#> 
#> Coefficients:
#>             Estimate Std. Error t value Pr(>|t|)    
#> (Intercept) -17.5791     6.7584  -2.601   0.0123 *  
#> speed         3.9324     0.4155   9.464 1.49e-12 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 15.38 on 48 degrees of freedom
#> Multiple R-squared:  0.6511, Adjusted R-squared:  0.6438 
#> F-statistic: 89.57 on 1 and 48 DF,  p-value: 1.49e-12
Phil
  • 7,287
  • 3
  • 36
  • 66
ZairaRosas
  • 27
  • 4
  • 1
    What kind of summary do you want? Just the regression equation or something that looks more like the whole model summary? [This](https://stackoverflow.com/questions/50639720/how-to-display-results-of-summary-as-plot-grob) post talks about putting model summaries into a graph, though using `ggplot` rather than `scatter.smooth`. – DaveArmstrong Jan 26 '21 at 23:23

2 Answers2

3

What you want to do is surprisingly difficult, which is why most people would not choose to do it that way :)

The closest solution I could find uses ggplot2 and a lot of other packages. It's possible to do the following:

  1. Create a summary table of the regression model using stargazer::stargazer()
  2. Convert that to a PNG image file using kableExtra::as_image()
  3. Convert the PNG to a grob using grid::rasterGrob()
  4. Use ggplot2::annotation_custom() to embed the table-as-image-as-grob into a ggplot2 chart

Note that as_image() requires some other packages and an installation of phantomjs.

Here's an example:

enter image description here

However, there are other solutions that might be better such as a simple summary using ggpubr::stat_regline_equation() or adding a table grob using the output of broom::tidy().

I think the simplest way to demonstrate all the options is in a RMarkdown file. Here is the code to copy into an RMarkdown file which you can knit in RStudio.

---
title: "Regression"
author: "Neil Saunders"
date: "27/01/2021"
output:
  html_document: 
    toc: yes
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE,
                      message = FALSE,
                      fig.path = "figures/")
library(ggplot2)
library(ggpubr)
library(broom)
library(gridExtra)
library(kableExtra)
library(grid)
library(sjPlot)
library(stargazer)
library(png)

theme_set(theme_bw())
```

# The model
```{r echo=TRUE}
linearMod <- cars %>% 
  lm(dist ~ speed, data = .)
```

# Visualizations

## Add equation and adjusted R-squared to a plot
```{r}
cars %>% 
  ggplot(aes(speed, dist)) +
  geom_point() +
  geom_smooth(method = "lm") +
  stat_regline_equation(
    aes(label =  paste(..eq.label.., ..adj.rr.label.., sep = "~~~~"))
  )
```

## Add tidy summary table to a plot
```{r}
linearMod_tidy <- tidy(linearMod)

cars %>% 
  ggplot(aes(speed, dist)) +
  geom_point() +
  geom_smooth(method = "lm") +
  annotation_custom(tableGrob(linearMod_tidy, 
                    theme = ttheme_default(base_size = 10)), 
                    xmin = 0, ymin = 90)
```


## Add tabular summary and plot side-by-side
### stargazer

:::::: {.columns}
::: {.column width="48%" data-latex="{0.48\textwidth}"}
```{r}
cars %>% 
  ggplot(aes(speed, dist)) +
  geom_point() +
  geom_smooth(method = "lm")
```
:::
::: {.column width="4%" data-latex="{0.04\textwidth}"}
\ 
<!-- an empty Div (with a white space), serving as
a column separator -->
:::
:::::: {.column width="48%" data-latex="{0.48\textwidth}"}
```{r results='asis'}
stargazer(linearMod, type = "html")
```
:::
::::::

### tab\_model

:::::: {.columns}
::: {.column width="48%" data-latex="{0.48\textwidth}"}
```{r echo=FALSE,}
cars %>% 
  ggplot(aes(speed, dist)) +
  geom_point() +
  geom_smooth(method = "lm")
```
:::
::: {.column width="4%" data-latex="{0.04\textwidth}"}
\ 
<!-- an empty Div (with a white space), serving as
a column separator -->
:::
:::::: {.column width="48%" data-latex="{0.48\textwidth}"}
```{r}
tab_model(linearMod)
```
:::
::::::

## Add stargazer table to a plot

```{r}
imgfile <- stargazer(linearMod, type = "html") %>% 
  as_image()

img <- readPNG(imgfile)
g <- rasterGrob(img, interpolate = TRUE, width = 0.5, height = 0.5)

cars %>% 
  ggplot(aes(speed, dist)) +
  geom_point() +
  geom_smooth(method = "lm") +
  annotation_custom(g, xmin = 1, xmax = 15, ymin = 50, ymax = 130)
```
neilfws
  • 32,751
  • 5
  • 50
  • 63
0

This is not exactly what you want because it does not use stargazer, but it seems more straightforward than the other (otherwise very instructive and nice!) approach, so it might give you some ideas. Of course, if you save your table as a JPG image using any package, you'll be able to use the same strategy as this.

I'll use the cowplot, ggplot2 and modelsummary packages:

library('modelsummary')
library('ggplot2')
library('cowplot')

First, we estimate a model and use modelsummary to save the table as a PNG file:

mod = lm(hp ~ mpg, mtcars)

modelsummary(mod, output = "table.png")

Then we create our basic ggplot2 plot:

p = ggplot(mtcars, aes(hp, mpg)) +
    geom_point() + 
    geom_smooth(method = "lm")

Finally, we use the ggdraw and draw_image functions from the cowplot package to insert the table picture in our plot:

ggdraw(p) +
  draw_image("table.png", x = .6, y = .5, width = .3, height = .5)

Vincent
  • 15,809
  • 7
  • 37
  • 39