0

I have a line plot in ggplot2 that is faceted by a categorical variable, and within each faceted plot, the lines are colored by a different categorical variable. I fit a model based on the second categorical variable within the faceted plots. I then want the plots to display the slope + r^2 of the regression line for each.

The answer to this question works, but only on a non-faceted plot with a single regression line, and I have been unable to find how to accomplish this in my circumstances.

I created some sample data...

ex.ID <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8)
ex.month <- c(0,6,12,18,24,0,6,12,18,24,0,6,12,18,24,0,6,12,18,24,0,6,12,18,24,0,6,12,18,24,0,6,12,18,24,0,6,12,18,24)
ex.label <- c("A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","A","A","A","A","A")
ex.score <- c(100,100,89,85,70,95,90,90,86,80,84,80,71,68,60,100,100,98,90,92,100,95,90,85,80,98,96,90,83,81,85,80,78,72,69,95,90,89,85,80)
ex.status <- c("Y","Y","Y","Y","Y","Z","Z","Z","Z","Z","Y","Y","Y","Y","Y","Y","Y","Y","Y","Y","X","X","X","X","X","Z","Z","Z","Z","Z","Y","Y","Y","Y","Y","X","X","X","X","X")

ex.df <- data.frame(ex.ID,ex.month,ex.label,ex.score,ex.status)

I then plotted in the ggplot2 package.

   ggplot(ex.df)+
     geom_line(aes(x=ex.month,y=ex.score,group=ex.ID,color=ex.status)) +
     facet_grid(.~ex.label) +
     geom_smooth(aes(x=ex.month,y=ex.score,group=ex.status),method="lm")

Graphygraph

I want to be able to display the slope and r^2 of each of these individual models on my graph. Is there some way to accomplish this on a faceted plot with multiple regression lines?

David
  • 259
  • 1
  • 2
  • 8
  • 1
    A number of solutions to this issue are presented in [this similar question](https://stackoverflow.com/questions/19699858/ggplot-adding-regression-line-equation-and-r2-with-facet). – Tiffany Jul 18 '17 at 20:38

1 Answers1

1

Here is a solution using by to generate the annotation for each group:

# Generate a data.frane with the annotation for each group
lm_eqn <- function(df){
  m <- lm(ex.score~ex.month , 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)))
  data.frame(ex.label=df$ex.label[1],ex.status = df$ex.status[1],label=as.character(as.expression(eq)) )

  }


# Group by ex.label(used in facet) and ex.ID (aes group on geom_smooth)
ll <-by(ex.df, list(ex.df$ex.label, ex.df$ex.status),lm_eqn, simplify = F)

# bind the groups
ldf <- do.call(rbind,ll)

# Generate the plot
ggplot(ex.df)+
  geom_line(aes(x=ex.month,y=ex.score,group=ex.ID,color=ex.status)) +
  facet_grid(.~ex.label) +
  geom_text(aes(x=15, y = 100+as.numeric(ldf$ex.status), label = label, color=ex.status), data=ldf, parse = TRUE, show.legend = F) +
  geom_smooth(aes(x=ex.month,y=ex.score,group=ex.status, color=ex.status),method="lm")

enter image description here

Marcelo
  • 4,234
  • 1
  • 18
  • 18
  • Thank you for your help. In the first block of code, is "df" referring to the original dataframe, or is it creating something new within a function? @Marcelo – David Jul 19 '17 at 14:32
  • 1
    `df` is the function argument. `by` will split the original data.frame according to the groups and call the function for each new data.frame. – Marcelo Jul 19 '17 at 15:22