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)
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