hny
hny

Reputation: 78

Why do geom_smooth nls and the standalone nls give different fit results?

When I fit my data using geom_smooth nls, I get a really nice fit. But if I use the stand alone nls function to fit my data using the same equation and starting values, I get a much poorer fit. I want to extract fit parameters so really need the standalone nls to generate the same fit as the geom_smooth nls.

Any suggestion/hint at what might be going on?


df <- data.frame("x" = c(4.63794469, 1.54525711, 0.51508570, 0.17169523, 0.05737664, 5.11623138, 1.70461130, 0.56820377, 0.18940126, 0.06329358, 0.02109786), 
                 "y" = c(0.1460101, 0.7081954, 0.9619413, 1.0192286, 1.0188301, 0.3114495, 0.7602488, 0.8205661, 0.9741323, 1.0922553, 1.1130464))

fit <- nls(data = df, y ~ (1/(1 + exp(-b*x + c))), start = list(b=1, c=0))
df$stand_alone_fit <- predict(fit, df)

df %>% ggplot() +
  geom_point(aes(x = x, y = y)) +
  scale_x_log10() +
  ylim(0,1.2) +
  geom_smooth(aes(x = x, y = y), method = "nls", se = FALSE, 
              method.args = list(formula = y ~ (1/(1 + exp(-b*x + c))), start = list(b= 1, c=0))) +
  geom_line(aes(x = x, y = stand_alone_fit), color = "red") +
  labs(title = "Blue: geom_smooth nls fit\nRed: stand alone nls fit")

enter image description here

Upvotes: 1

Views: 423

Answers (1)

Dave2e
Dave2e

Reputation: 24129

Two issues here, first the prediction (red line) is only performed at for the x points cause the curve to look boxy and not smooth.

Second and the reason for the question. The two fitted curves are not equal is because there is transformation on the x axis due to this line scale_x_log10() so the nls function inside the geom_smooth is performing a different fit than the standalone fit.

See what happens when the x-axis transformation is removed. (the green line is a finer prediction from the external fit).

df <- data.frame("x" = c(4.63794469, 1.54525711, 0.51508570, 0.17169523, 0.05737664, 5.11623138, 1.70461130, 0.56820377, 0.18940126, 0.06329358, 0.02109786), 
                 "y" = c(0.1460101, 0.7081954, 0.9619413, 1.0192286, 1.0188301, 0.3114495, 0.7602488, 0.8205661, 0.9741323, 1.0922553, 1.1130464))


fit <- nls(data = df, y ~ (1/(1 + exp(-b*x + c))), start = list(b=0, c=0))
df$stand_alone_fit <- predict(fit, df)

#finer resolution (green line)
new <- data.frame(x=seq(0.02, 5.1, 0.1))
new$y <-predict(fit, new)

df %>% ggplot() +
   geom_point(aes(x = x, y = y)) +
#   scale_x_log10() +
   ylim(0,1.2) +
   geom_smooth(aes(x = x, y = y), method = "nls", se = FALSE, 
               method.args = list(formula = y ~  (1/(1 + exp(-b*x + c))), start = list(b=0, c=0))) +
   geom_line(aes(x = x, y = stand_alone_fit), color = "red") +
   geom_line(data=new, aes(x, y), color="green") +
   labs(title = "Blue: geom_smooth nls fit\nRed: stand alone nls fit")

enter image description here

Or use this in your original ggplot definition: method.args = list(formula = y ~ (1/(1 + exp(-b*10^(x) + 2*c))), start = list(b=-1, c=-3)))

Upvotes: 3

Related Questions