Displaying geom_smooth() trend line from a specified x value

I went to look at the after_stat function mentioned by @tjebo. See if the following works for you?

df %>%
  ggplot(aes(x = week,
             y = rate,
             lty = group)) + 
  geom_line() +
  geom_point() +
  geom_smooth(method = "glm", 
              aes(group = after_stat(interaction(group, x > 35)),
                  colour = after_scale(alpha(colour, as.numeric(x > 35)))),
              method.args = list(family = "quasipoisson"),
              se = F)

result

This works by splitting the points associated with each line into two groups, those in the x <=35 region and those in the x >35 region, since a line's colour shouldn't vary, and defining a separate colour transparency for each new group. As a result, only the lines in the x > 35 region are visible.

When used, the code triggers a warning that the after_scale modification isn't applied to the legend. I don't think that's a problem though, since we don't need it to appear in the legend anyway.


If you can tolerate a warning, you can solve this with 1 line difference from the example code using stage().

library(tidyverse)

set.seed(123)
df <- data.frame(group = as.factor(rep(1:3, each = 50)),
                 week = rep(1:50, 3),
                 rate = c(round(700 - rnorm(50, 100, 10) - 1:50 * 2, 0),
                          round(1000 - rnorm(50, 200, 10) - 1:50 * 2, 0),
                          round(1000 - rnorm(50, 200, 10) - 1:50 * 2, 0)))

df %>%
  ggplot(aes(x = week,
             y = rate,
             group = group,
             lty = group)) + 
  geom_line() +
  geom_point() +
  geom_smooth(method = "glm", 
              method.args = list(family = "quasipoisson"),
              aes(x = stage(week, after_stat = ifelse(x > 35, x, NA))),
              se = FALSE) 
#> `geom_smooth()` using formula 'y ~ x'
#> Warning: Removed 165 rows containing missing values (geom_smooth).


One way to do this is to construct the fitted values outside of ggplot so you have control over them:

df$fit <- glm(rate ~ week + group, data = df, family = "quasipoisson")$fitted.values

library(dplyr)
library(ggplot2)

ggplot(df, aes(x = week, group = group, lty = group)) + 
  geom_line(aes(y = rate)) +
  geom_point(aes(y = rate)) +
  geom_line(data = df %>% filter(week >= 35), aes(y = fit), color = "blue", size = 1.25)

enter image description here

Tags:

R

Ggplot2