1

I have use NLS to fit the Lidar waveform data. It seems work for 3 or 4 peaks. for (i in 1:3){ mean <- c(mean,realind[i]) }

sd=runif(3,6,20)
c=runif(3,100,250)
df<-data.frame(x=seq_along(y),y)
fit<-nls(y ~(c1 * exp(-(x - mean1)**2/(2 * sigma1**2)) +
         c2 * exp(-(x - mean2)**2/(2 * sigma2**2))+
         c3 * exp(-(x - mean3)**2/(2 * sigma3**2))), data=df,
         start=list(c1=c[1], mean1=mean[1], sigma1=sd[1],
                    c2=c[2], mean2=mean[2], sigma2=sd[2],
                    c3=c[3], mean3=mean[3], sigma3=sd[3]), algorithm="port")

But the question is every time you have to manual written this long formulas and parameters of start. So I wonder how can I automatically generate a function by a loop, then the formulas=y~f(x,c,mean,sd) and also start pars can be generate by a loop. And make sure these can work in nls. Also I hope you guys could give me some suggestions about multi peak Gaussian fit, I have tried GPfit, GMM.

The one who also have the same problem with me in this website, but it does not get the satisfying answers. You can refer to it by nls when the data is a convoluted spectra (variable number of variables)

Community
  • 1
  • 1

1 Answers1

0

You've crammed a lot of questions in here. I'll answer what seems like the main one. You can build formula as a string. Then you can convert it to a formula. And it's not that hard to build a list with the initial parameters you want. Here's such a function

gennls <- function(c, mean, sd) {
    n <- seq_along(c)
    fs <- paste("y ~", 
        paste(
            paste0("c",n, " * exp(-(x-mean",n,")**2/(2 * sigma",n,"**2))"),
        collapse=" + ")
    )
    names(c)<-paste0("c",seq_along(c))
    names(mean)<-paste0("mean",seq_along(c))
    names(sd)<-paste0("sigma",seq_along(sd))
    list(
        formula=as.formula(fs),
        start=c(as.list(c), as.list(mean), as.list(sd))
    )
}

And then you can run it with

init <- gennls(runif(3), runif(3), runif(3))

And that will return a list with a formula

init$formula
# y ~ c1 * exp(-(x - mean1)^2/(2 * sigma1^2)) + c2 * exp(-(x - 
#     mean2)^2/(2 * sigma2^2)) + c3 * exp(-(x - mean3)^2/(2 * sigma3^2))

and the initial parameters

str(iniy$start)
# List of 9
#  $ c1    : num 0.883
#  $ c2    : num 0.0521
#  $ c3    : num 0.664
#  $ mean1 : num 0.665
#  $ mean2 : num 0.902
#  $ mean3 : num 0.449
#  $ sigma1: num 0.672
#  $ sigma2: num 0.429
#  $ sigma3: num 0.865
MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • I am very appreciated your answer. But it seems did not work in nls. my code is like this. init <- gennls(runif(3,100,250), runif(3,25,90), runif(3,6,20)) init$formula init$start df<-data.frame(x=seq_along(y),y) fit<-nls(init$formula,data=df,start=init$start,algorithm="port"). – user3701176 Jun 04 '14 at 21:15
  • @user3701176 There was a typo in one of the starting parameter list names in my `gennls` function. I've updated the code. Try it again. – MrFlick Jun 04 '14 at 21:22