Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
661 views
in Technique[技术] by (71.8m points)

ggplot2 - R: nls not picking up additional arguments when used in custom function in geom_smooth

This is a question that relates to my earlier question geom_smooth with facet_grid and different fitting functions. In that question, I was trying to use a different fitting function in geom_smooth for each facet in a facet grid for ggplot2. Marco Sandri kindly provided an answer that I am trying to adapt to use user-defined formulas rather than existing formulas (e.g., lm, loess). Here is the my code.

# Load library
library(ggplot2)

# Load data
data(mtcars)

# Smoothing function with different behaviour depending on the panel
custom.smooth <- function(formula, data,...){
  smooth.call <- match.call()

  if(as.numeric(unique(data$PANEL)) == 6) {
    # Nonlinear regression
    method.name <- eval(parse(text="nls"))
    # Specify formula
    formula <- as.formula("y ~ a * x^b")
    # Add initial parameters
    smooth.call[["start"]] <- c(a = 10, b = -0.5)
  }else{
    # Linear regression
    method.name <- eval(parse(text="lm"))
  }

  # Add function name
  smooth.call[[1]] <- method.name
  # Perform fit
  eval.parent(smooth.call)
}

# Plot data with custom fitting function
p <- ggplot(mtcars,aes(x = disp, y = mpg)) + geom_point() + facet_grid(gear ~ am)
p <- p + geom_smooth(method = "custom.smooth")
print(p)

In this code, I define a function custom.smooth that chooses the model to be fit. In this example, all models are linear regressions except for panel 6, which is a user-defined function y ~ a*x^b. Running this code gives the error:

Warning message: Computation failed in stat_smooth(): singular gradient matrix at initial parameter estimates

Nevertheless, when I run nls on the data in panel 6 with these initial parameters I get no such error (i.e., nls(mpg ~ a * disp^b, mtcars %>% filter(gear == 5, am == 1), start = c(a = 10, b = -0.5))). This makes me think that nls isn't seeing the start values I specify. I have also tried specifying these parameters in the geom_smooth function like this:

p <- p + geom_smooth(method = "custom.smooth", method.args = list(start = c(a = 10, b = -0.5)))

but I run into the same issue. Any ideas how I can get my start values to nls? Or is there another reason why the code isn't working?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's the solution, which greatly benefited from this post. I don't know why the previous version didn't work, but this seems to work fine.

# Load library
library(ggplot2)

# Load data
data(mtcars)

# Smoothing function with different behaviour depending on the panel
custom.smooth <- function(formula, data,...){
  smooth.call <- match.call()

  if(as.numeric(unique(data$PANEL)) == 6) {
    # Nonlinear regression
    smooth.call[[1]] <- quote(nls)
    # Specify formula
    smooth.call$formula <- as.formula("y ~ a * x ^ b")
    # Add initial parameters
    smooth.call$start <- c(a = 300, b = -0.5)
  }else{
    # Linear regression
    smooth.call[[1]] <- quote(lm)
  }

  # Perform fit
  eval.parent(smooth.call)
}

# Plot data with custom fitting function
p <- ggplot(mtcars,aes(x = disp, y = mpg)) + geom_point() + facet_grid(gear ~ am)
p <- p + geom_smooth(method = "custom.smooth", se = FALSE)
print(p)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...