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
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)
Solution 3
Using gridExtra
you can arrange yours plots like this.
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)
Related videos on Youtube
![TheComeOnMan](https://i.stack.imgur.com/MZg5c.png?s=256&g=1)
Author by
TheComeOnMan
Updated on July 05, 2022Comments
-
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 over 10 yearsBetter to give some reproducible data and provide what you have tried...
-
TheComeOnMan over 10 yearsThe 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 over 10 yearsThanks, but I need the equation more importantly.
-
sckott over 10 yearsI think you can pass a vector/list/etc. to
annotate
, like this stackoverflow.com/questions/11889625/… -
TheComeOnMan over 10 years@agstudy, I'm trying to use
annotate
instead ofgeom_text
but I'm unable to pass theeq
dataframe or the columneq$V1
to it. Could you help me with that please? -
TheComeOnMan over 10 yearsYou'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 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 over 10 yearsNo problem. However I don't think
annotate
works like that withfacet_grid
. agstudy's approach is just completely different. But I could be wrong. -
TheComeOnMan over 10 yearsThanks.
grid.arrange
seems to work more likefacet_wrap
thanfacet_grid
. Is that right? If so, I would like to get thefacet_grid
sort of solution to work. -
sckott over 10 yearsHmm, I guess that doesn't work does it. Editing answer above with a gridextra solution that I use often
-
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 recreateloess
, then presume I have set all my parameters / assumptions correctly. Isn't there a simpleshow.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 over 8 yearsIt 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 about 5 yearsAs of R 3.5 at least,
format()
does not discard anymore thenames
attribute ofcoef(m)[1]
and thelm_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 withas.numeric(coef(m)[1])
, etc.