Search code examples
rggplot2regressionnls

How to assign different initial values inside geom_smooth() (from the ggplot2 package) for multiple nonlinear regressions?


I have 2 datasets, one for group A and one for group B. I want to visually fit the data into the y=1-exp(-kx) model. For this I'm using the ggplot2 package and the geom_smooth() function. Within the arguments of the geom_smooth() function it is necessary to indicate initial values for non-linear fits. As I have 2 sets of data, I would like to assign different initial values to each set. In this case, for group A the initial value of k would be 0.45 and for group B it would be 0.015. However, I don't know how to do this. Can anybody help me?

library(ggplot2)


Group <- c("A", "B")
x <- 0:10
y <- c(0, 0.4, 0.6, 0.8, 0.9, 0.9, 0.95, 0.97, 0.98, 0.99, 1,
       0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1)
start_values <- c(0.45, 0.015)

df <- expand.grid(x = x,
                  Group = Group)

df$y <- y

ggplot(data = df,
       aes(x = x,
           y = y)) +
  geom_point(aes(shape = Group,
                 color = Group)) +
  geom_smooth(aes(color = Group),
              formula = y ~ 1-exp(-k*x),
              method = "nls",
              method.args = list(k = start_values),
              se = FALSE)

enter image description here


Solution

  • As far as I can tell, you cannot easily pass different parameters for each group using geom_smooth. One option would be to add separate layers for each of the groups

    ggplot(data = df,
           aes(x = x,
               y = y)) +
      geom_point(aes(shape = Group,
                     color = Group)) +
      geom_smooth(aes(color = Group),
                  formula = y ~ 1-exp(-k*x),
                  method = "nls",
                  method.args = list(start = c(k=start_values[1])),
                  se = FALSE, data = function(x) subset(x, Group=="A")) + 
      geom_smooth(aes(color = Group),
                  formula = y ~ 1-exp(-k*x),
                  method = "nls",
                  method.args = list(start = c(k=start_values[2])),
                  se = FALSE, data = function(x) subset(x, Group=="B"))
    

    enter image description here Rather than manually adding a layer for each group, you can also use mapply to create them for you

    ggplot(data = df,
           aes(x = x,
               y = y)) +
      geom_point(aes(shape = Group,
                     color = Group)) +
      mapply(function(start, group) {
        geom_smooth(aes(color = Group),
              formula = y ~ 1-exp(-k*x),
              method = "nls",
              method.args = list(start = c(k=start)),
              se = FALSE, data = function(x) subset(x, Group==group))  
      }, start_values, c("A","B"))