Junitar
Junitar

Reputation: 999

Plot multiple linear regressions from tibble of intercepts and slopes using ggplot

I have a tibble fit of intercepts alpha and slopes beta from multiple linear regressions. Dput data below.

I would like to exponentiate and plot each regression in the same plot window such that y = exp(alpha + beta * x).

Here is a "test" plot I made to figure out how to do it:

ggplot() +
  stat_function(fun = ~ for (i in 1:nrow(fit)) {
    exp(fit$alpha[i] + fit$beta[i] * seq(0, 10, .01))
  }) +
  theme_classic() +
  xlim(0, 10) +
  ylim(0, 1000)

It doesn't work though and I get the following warning that I'm not sure to understand:

Computation failed in `stat_function()`:
Elements must equal the number of rows or 1 

Also, is there a ggplot function that iterates through each regression directly so that I don't have to use a loop? I know that geom_abline() can do that with the intercepts and slopes but I'm not able to exponentiate the regressions.

Data:

structure(list(alpha = c(6.4860289555265, 6.27396167268318, 
6.32039803132685, 6.30814751731013, 5.57998066302655, 6.48871720571395, 
6.33967399748598, 6.48688731183521, 6.26045779265403, 6.2953943578198, 
6.20448822286806, 6.50154201141595, 6.1774295664319, 6.02222511089118, 
6.2716610722266, 6.21255274086976, 5.79004244768028, 6.35653188128858, 
6.26422754017315, 6.11397557151798, 6.4758221837802, 6.20707829503994, 
6.11614443128677, 6.03290796195398, 6.04382957704095, 6.24508205522959, 
5.59411842610983, 6.33452203853571, 6.42799288311273, 6.21094379710094, 
5.96247571920146, 6.32340649837508, 6.00574461437739, 5.98586711865563, 
5.90996559415481, 5.85960458364359, 6.07748580916622, 6.38297427956585, 
6.30105414357071, 6.50276479896593, 6.35108145640532, 6.11115445717759, 
6.06048094442664, 6.39924383968502, 6.29705245347993, 6.132325962512, 
6.08533361080762, 6.11299308468399, 5.99317043822914, 6.64345246270652
), beta = c(-0.240706094587343, -0.118050194208012, -0.183066432959319, 
-0.155331773463964, -0.136034449469665, -0.148786968695725, -0.138424348731508, 
-0.182977715878648, -0.14492872413148, -0.0917393831564791, -0.137963572824426, 
-0.154072673769774, -0.197768747696995, -0.109498466316583, -0.134228657790289, 
-0.162007411722827, -0.120537296889171, -0.147596027060241, -0.144570831735452, 
-0.136825094924608, -0.193485685316959, -0.208054563949588, -0.138275798744531, 
-0.115652152539183, -0.0723231611644853, -0.19880444266469, -0.138168835432978, 
-0.132242987514684, -0.171978838679919, -0.164295833035347, -0.0986271579815662, 
-0.149522368532541, -0.196407247053081, -0.19111792294904, -0.132103384320777, 
-0.107138921917582, -0.109487704684017, -0.186037683605527, -0.258118158119251, 
-0.132779176452371, -0.17328572497824, -0.194029734577603, -0.116892149681328, 
-0.193838711732235, -0.15427710341968, -0.143054577800488, -0.115065744720938, 
-0.153687083514263, -0.138507868513552, -0.178604854161425)), row.names = c(NA, 
-50L), class = c("tbl_df", "tbl", "data.frame"))

Upvotes: 0

Views: 201

Answers (2)

Edo
Edo

Reputation: 7858

You can calculate x and y before the ggplot in this way:

library(dplyr)
library(ggplot2)

fit %>%
 mutate(model = row_number()) %>%
 rowwise(model, alpha, beta) %>%
 summarise(x = seq(0, 10, .01),
           y = exp(alpha + beta * x)) %>% 
 
 ggplot() +
 geom_line(aes(x = x, y = y, colour = factor(model)), show.legend = FALSE) +
 theme_classic() +
 xlim(0, 10) +
 ylim(0, 1000)

enter image description here


EDIT:

Just a quick update to see the difference between the approach with dplyr and purrr in terms of efficiency:

microbenchmark::microbenchmark(
dplyr = fit %>%
 mutate(model = row_number()) %>%
 rowwise(model, alpha, beta) %>%
 summarise(x = seq(0, 10, .01),
           y = exp(alpha + beta * x), 
           .groups = "drop") %>% 
 
 ggplot() +
 geom_line(aes(x = x, y = y, colour = factor(model)), show.legend = FALSE) +
 theme_classic() +
 xlim(0, 10) +
 ylim(0, 1000),


purr = ggplot() +
 purrr::map(1:nrow(fit), ~ geom_function(fun = function(x) exp(fit$alpha[.x] + fit$beta[.x] * x))) +
 theme_classic() +
 xlim(0, 10) +
 ylim(0, 1000)

) %>% plot()

enter image description here

The dplyr solution is way faster.

Upvotes: 1

stefan
stefan

Reputation: 125208

Making use of purrr::map and geom_function this could be achieved like so:

library(ggplot2)

ggplot() +
  purrr::map(1:nrow(fit), ~ geom_function(fun = function(x) exp(fit$alpha[.x] + fit$beta[.x] * x))) +
  theme_classic() +
  xlim(0, 10) +
  ylim(0, 1000)

Upvotes: 1

Related Questions