ggplot: Adding Regression Line Equation and R2 with Facet

49,051

Solution 1

Here is an example starting from this answer

require(ggplot2)
require(plyr)

df <- data.frame(x = c(1:100))
df$y <- 2 + 3 * df$x + rnorm(100, sd = 40)


lm_eqn = function(df){
    m = lm(y ~ x, df);
    eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, 
         list(a = format(coef(m)[1], digits = 2), 
              b = format(coef(m)[2], digits = 2), 
             r2 = format(summary(m)$r.squared, digits = 3)))
    as.character(as.expression(eq));                 
}

Create two groups on which you want to facet

df$group <- c(rep(1:2,50))

Create the equation labels for the two groups

eq <- ddply(df,.(group),lm_eqn)

And plot

p <- ggplot(data = df, aes(x = x, y = y)) +
            geom_smooth(method = "lm", se=FALSE, color="black", formula = y ~ x) +
            geom_point()
p1 = p + geom_text(data=eq,aes(x = 25, y = 300,label=V1), parse = TRUE, inherit.aes=FALSE) + facet_grid(group~.)
p1 

enter image description here

Solution 2

Does this do what you want?

library(ggplot2); library(gridExtra)
ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
  geom_point() +
  geom_smooth(method="lm") +
  facet_wrap(~ Species)

grid.newpage()
vpa_ <- viewport(width = 1, height = 1)
print(p, vp = vpa_)
grid.text("y ~ mx + b", x=0.3, y=0.8)
grid.text("y ~ mx + b", x=0.5, y=0.8)
grid.text("y ~ mx + b", x=0.8, y=0.8)

enter image description here

Solution 3

Using gridExtra you can arrange yours plots like this.

enter image description here

library(ggplot2)

library(ggplot2)
iris$x = iris$Sepal.Length 
iris$y = iris$Sepal.Width
xx <- range(iris$x)
yy <- range(iris$y)

ll <- by(iris,iris$Species,function(df){
  x.eq <- max(xx)-mean(xx)/2
  y.eq <- max(yy)*0.95
  p <- ggplot(df, aes(x, y)) +
    geom_point() +
    geom_smooth(method="lm") +
    annotate(x=x.eq, y =y.eq ,  geom='text',
              label = lm_eqn(df), size=5,parse=TRUE) +
    xlim(xx[1],xx[2])+ylim(yy[1],yy[2])
})

library(gridExtra)
do.call(grid.arrange,ll)
Share:
49,051

Related videos on Youtube

TheComeOnMan
Author by

TheComeOnMan

Updated on July 05, 2022

Comments

  • TheComeOnMan
    TheComeOnMan almost 2 years

    I've created a faceted scatterplot with ggplot but I'm struggling to add the regression line equation to each of the facets. The simple case where there is no faceting has been answered here but this method won't extend to a faceted plot.

    Any ideas how to accomplish this in a clean fashion?

    • agstudy
      agstudy over 10 years
      Better to give some reproducible data and provide what you have tried...
    • TheComeOnMan
      TheComeOnMan over 10 years
      The suggested duplicate points to a link that I have already provided in my question. One of the comments on that link, which wasn't answered, also asks the same question of how to add the equation on a faceted plot. The trick seems to be to pass a vector/data.frame for the labels. I don't believe this is a duplicate.
  • TheComeOnMan
    TheComeOnMan over 10 years
    Thanks, but I need the equation more importantly.
  • sckott
    sckott over 10 years
    I think you can pass a vector/list/etc. to annotate , like this stackoverflow.com/questions/11889625/…
  • TheComeOnMan
    TheComeOnMan over 10 years
    @agstudy, I'm trying to use annotate instead of geom_text but I'm unable to pass the eq dataframe or the column eq$V1 to it. Could you help me with that please?
  • TheComeOnMan
    TheComeOnMan over 10 years
    You're probably right. In the link you've put, the answered isn't passing a vector to annotate though. Do you know how to do that?
  • TheComeOnMan
    TheComeOnMan over 10 years
    @JT85, irrespective of the above comment, your answer works perfectly well for my current problem which is why I've accepted it already. I'd still like to use annotate instead though.
  • Jonas Tundo
    Jonas Tundo over 10 years
    No problem. However I don't think annotate works like that with facet_grid. agstudy's approach is just completely different. But I could be wrong.
  • TheComeOnMan
    TheComeOnMan over 10 years
    Thanks. grid.arrange seems to work more like facet_wrap than facet_grid. Is that right? If so, I would like to get the facet_grid sort of solution to work.
  • sckott
    sckott over 10 years
    Hmm, I guess that doesn't work does it. Editing answer above with a gridextra solution that I use often
  • Mike Williamson
    Mike Williamson over 8 years
    @JT85 This is a great work around, but it leaves one major flaw, IMHO. The line is plotted using different code than the actual equation. For a simple linear least squares, big deal. But what if I, for instance, wanted to use the nice loess polynomial fit. I would have to recreate loess, then presume I have set all my parameters / assumptions correctly. Isn't there a simple show.eqn flag or something like that? If not, why? That seems so fundamental to a regression fit! (BTW, I know it's not your code. Just asking the general crowd here...)
  • Mark Lakata
    Mark Lakata over 8 years
    It appears that , inherit.aes=FALSE is not necessary to get the same output, but perhaps this was inserted for an older version of R or ggplot. I have R 3.2.3 and ggplot 2.1.0
  • Charles Plessy
    Charles Plessy about 5 years
    As of R 3.5 at least, format() does not discard anymore the names attribute of coef(m)[1] and the lm_eqn(df) function returns "italic(y) == c(`(Intercept)` = \"-0.83\")… instead of somehing like "italic(y) == \"-0.83\" …. This can be corrected by discarding name attributes with as.numeric(coef(m)[1]), etc.