[R] non linear regression with nls

lauramorgana at bluewin.ch lauramorgana at bluewin.ch
Thu Feb 5 10:14:51 CET 2009


Thank you a lot Mr. Ritz!
I've tried the loop you suggested and I added a list for lower and upper limits of the parameters, but there is still 
a problem... 

I have a list of functions, which works...
fz1<-function(Portata, a, b){a+(b/Portata)} 
fz2<-function(Portata, a, b){a*exp(b*Portata)}
fz3<-function(Portata, a, b, d, e){a+(b/Portata)+d*(Portata^e)}
fz4<-function(Portata, a, b){a*Portata^b}
fz5<-function(Portata, a, b, d){a+b*(Portata^d)}
fctList <- list(fz1, fz2, fz3, fz4, fz5)

as well as lists for starting values, upper and lower values, which work as well:
startList <- list(list(a=10, b=10), list(a=10, b=1), list(a=10, b=10, d=10, e=1), list(a=10, b=1), list(a=10, b=10, 
d=1))
lowerList<-list(list(a=0,b=0),list(a=0,b=0), list(a=0,b=0,d=0,e=-50),list(a=0, b=-50), list(a=0, b=0, d=-50))
upperList<-list(list(a=1000, b=1000), list(a=1000, b=1000), list(a=1000,b=1000,d=1000,e=50), list(a=1000,b=50), list
(a=1000, b=1000, d=50))

but if I try to run this for loop


resultList <- list()
for (i in 1:5)
{
resultList[[i]] <- nls(NT.N ~ fctList[[i]](Portata, a,b), data=subset(dati, Fiume=="Laveggio"), start=startList[[i]], 
nls.control(maxiter=200), algorithm='port', trace=TRUE, na.action=na.omit, upper=upperList[[i]], lower=lowerList[[i]])
}
 I get the following error message:
"Error in fctList[[i]](Portata, a, b) : element 1 is empty;
   the part of the args list of '*' being evaluated was:
   (d, (Portata^e))"

I realized that the problem is the element after the function, i.e. (Portata, a, b), since fct 3 and 5 have more 
parameters (Portata,a,b,d,e).
So I tried to make a list (parList) for this too, i tried 2 versions:
#version1
list("Portata","a", "b")->pf1.2.4
list("Portata","a","b","d","e")->pf3
list("Portata","a","b","d")->pf5
parList<-list(pf1.2.4, pf1.2.4,pf3,pf1.2.4,pf5)

#version 2
parList<-list("Portata,a,b","Portata,a,b","Portata,a,b,d,e", "Portata,a,b","Portata,a,b,d")

and then I tried them (one at a time) in the loop:

resultList <- list()
for (i in 1:5)
{
    resultList[[i]] <- nls(NT.N ~ fctList[[i]](parList[[i]]), data=subset(dati, Fiume=="Laveggio"), start=startList
[[i]], nls.control(maxiter=200), algorithm='port', trace=TRUE, na.action=na.omit,upper=upperList[[i]], lower=lowerList
[[i]])
}
but I got this error message: " Error in fctList[[i]](parList[i]) : element 1 is empty;
   the part of the args list of '+' being evaluated was:
   (a, (b/Portata))"

What can I do to fix it?
I'm also wondering which kind of function (maybe another loop?) I could use to automize the regression not only for 
the variable NT.N but for every variable (PTG.P, PO4.P,. ..)

My dataframe look like this (a sample):

        Fiume giorno mese anno Portata  PTG.P   PO4.P   NT.N  NH4.N NO3.N   BOD5 SiO2  data
1    Vedeggio     10    1 1995   0.981 218.40 118.000  9.196 6.5700  2.06  6.080 4.33 34709
2    Vedeggio      7    2 1995   0.965 125.84  54.000  8.701 5.2600  2.31 16.480 4.43 34737
3    Vedeggio      7    3 1995   1.536  37.44  12.000  7.271 5.5600  1.88  5.240 4.15 34765
...
190 Cassarate     29    9 2008   1.240  26.00  20.000  2.480 0.1200  1.79  1.700 4.03 39720
191 Cassarate     13   10 2008   0.860  23.00  16.000  2.720 0.0200  2.13  1.780 3.71 39734
192 Cassarate     10   11 2008   8.840  26.00  14.000  2.900 0.0500    NA  1.400 3.62 39762
193 Cassarate      9   12 2008   2.030  35.00  23.000  2.190 0.0700  1.79  1.950 3.74 39791
...
279  Laveggio     15    1 2002   0.347  77.00  30.000  9.690 0.4300  7.23  1.950 4.17 37271
280  Laveggio     11    2 2002   0.527  54.00  17.000  7.520 0.8800  5.87  2.410 3.58 37298
281  Laveggio     13    3 2002   0.900  34.00  15.000  7.520 0.7100  6.17  6.550 3.03 37328
...
Thanks to anyone that could give me any hint!!
Laura




## a for loop
resultList <- list()
for (i in 1:5)
{
    ## storing the result as the i'th list component
    ## notice that the i'th list components in fctList and startList
    ## are used for the i'th fit
    resultList[[i]] <- nls(NT.N ~ fctList[[i]](parList[[i]]), data=subset(dati, Fiume=="Laveggio"), start=startList
[[i]], nls.control(maxiter=200), algorithm='port', trace=TRUE, na.action=na.omit)
}

----Messaggio originale----
Da: ritz at life.ku.dk
Data: 03.02.2009 19.00
A: <lauramorgana at bluewin.ch>
Oggetto: Re: [R] non linear regression with nls

Hi Laura,

I've the following suggestion for you using several lists and a "for" loop:


fz1<-function(Portata, a, b){a+b/Portata}
fz2<-function(Portata, a, b){a*exp(b*Portata)}
fz3<-function(Portata, a, b, d, e){a+b/Portata+d*(Portata^e)}
fz4<-function(Portata, b, d){b*Portata^d}
fz5<-function(Portata, a, b, d){a+b*(Portata^d)}
fctList <- list(fz1, fz2, fz3, fz4, fz5)

startList <- list(list(a=10, b=10), list(a=10, b=1), start=list(a=10, b=10, d=10, e=10),
list(a=10, b=1), list(a=10, b=10, d=1))

## a for loop
resultList <- list()
for (i in 1:5)
{
    ## storing the result as the i'th list component
    ## notice that the i'th list components in fctList and startList
    ## are used for the i'th fit
    resultList[[i]] <- nls(NT.N ~ fctList[[i]](Portata, a,b),
    data=subset(dati, river.name=="Laveggio"), start=startList[[i]],
    nls.control(maxiter=200), algorithm='port', trace=TRUE, na.action=na.omit)
}


summary(resultList[[1]])
plotfit(resultList[[1]])
summary(resultList[[2]])
plotfit(resultList[[2]])
...


I hope you can make it work?


Christian




More information about the R-help mailing list