I apologize for posting this in essence the second time (no light at the end of the tunnel yet..): is there a way to enforce that "nls" takes both, the data *and* the model definition from the parent environment? the following fragment shows the problem. #======== cut here=========wrapper <- function (choose=0) { x <- seq(0,2*pi,len=100) y <- sin(1.5*x); y <- rnorm(y,y,.1*max(y)) if (choose==0) { rm(fifu,pos=1) fifu <- function(w,x) {sin(w*x)} } else assign('fifu',function(w,x) {sin(w*x)},.GlobalEnv) res <- nls(y ~ fifu(w,x),start=list(w=1)) res } #======== cut here========= if called as "wrapper(1)" this runs fine because the fitting function "fifu" is assigned in the GlobalEnv. if called as "wrapper(0)", "fifu" is defined only locally and "nls" (actually, "nlsModel", I think) does not know what I'm talking about. I understand, the problem is that the scoping rules are such that "nls" does not resolve 'fifu' in the parent environment, but rather in the GlobalEnv. (this is different for the data, which *are* taken from the parent environment of the nls-call). I tried some variants of using "eval" but without starting to modify "nls" itself there seems no way (up to now, anyway). The solution to "assign" 'fifu' directly into the GlobalEnv does work, of course, but leads to the undesirable effect of accumulating objects in the workspace which are not needed there (and might overwrite existing ones). in response to my first post, I got the hint that for "lm" the situation is different: it handles the above situation as desired (i.e. accepts local model definition). in so far one might even argue that this behaviour of "lm" and "nls" leads to an inconsistent behaviour of R in quite similar situations (e.g. replacing at some point a linar model by a nonlinear model in some large project is not achieved by simply replacing "lm" by "nls" somewhere deep down in the source code). regards, joerg ______________________________________________ R-help at stat.math.ethz.ch mailing list https://www.stat.math.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
On Thu, 10 Jun 2004, joerg van den hoff wrote:> I apologize for posting this in essence the second time (no light at the > end of the tunnel yet..): > > is there a way to enforce that "nls" takes both, the data *and* the > model definition from the parent environment? the following fragment > shows the problem. > > #======== cut here=========> wrapper <- function (choose=0) > { > x <- seq(0,2*pi,len=100) > y <- sin(1.5*x); > y <- rnorm(y,y,.1*max(y)) > > if (choose==0) { > rm(fifu,pos=1) > fifu <- function(w,x) {sin(w*x)} > } > else > assign('fifu',function(w,x) {sin(w*x)},.GlobalEnv) > > res <- nls(y ~ fifu(w,x),start=list(w=1)) > res > } > #======== cut here=========> > if called as "wrapper(1)" this runs fine because the fitting function > "fifu" is assigned in the GlobalEnv. > if called as "wrapper(0)", "fifu" is defined only locally and "nls" > (actually, "nlsModel", I think) does not know what I'm talking about. > > I understand, the problem is that the scoping rules are such that "nls" > does not resolve 'fifu' in the parent environment, but rather in the > GlobalEnv. (this is different for the data, which *are* taken from the > parent environment of the nls-call).I assume by `data' you mean not the `data' argument to nls but the variables referred to in your formula.> I tried some variants of using "eval" but without starting to modify > "nls" itself there seems no way (up to now, anyway). > > The solution to "assign" 'fifu' directly into the GlobalEnv does work, > of course, but leads to the undesirable effect of accumulating objects > in the workspace which are not needed there (and might overwrite > existing ones).S has frame 1 for this purpose. The nearest equivalent I know in R is to attach an environment in position 2 and assign objects like 'fifu' there, which avoids your `undesirable effect'.> in response to my first post, I got the hint that for "lm" the situation > is different: it handles the above situation as desired (i.e. accepts > local model definition). in so far one might even argue that this > behaviour of "lm" and "nls" leads to an inconsistent behaviour of R in > quite similar situations (e.g. replacing at some point a linar model by > a nonlinear model in some large project is not achieved by simply > replacing "lm" by "nls" somewhere deep down in the source code).I think that is simply wrong. It is a _function_ in your non-linear model definition that is not being found, not the variables (which you call `data' above). You do currently need to ensure that the functions in your formulae are in scope when called from nlsModel. Around R 1.2.x the notion was introduced that variables should be looked for in the environment of a formula. Functions using model.frame got converted to do that, but nls did not. I guess that the best way forward is to ensure that nls (and nlsModel) does search the environment of the formula for functions. -- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
On Thu, 10 Jun 2004, Prof Brian Ripley wrote:> Around R 1.2.x the notion was introduced that variables should be looked > for in the environment of a formula. Functions using model.frame got > converted to do that, but nls did not. I guess that the best way forward > is to ensure that nls (and nlsModel) does search the environment of the > formula for functions.It transpires that is rather easy to achieve. At the top of nlsModel and nlsModel.plinear use env <- new.env(parent=environment(form)) instead of env <- new.env() This then automatically searches for objects used in the formula Notes 1) nls is in a namespace, so you need to fix the copy in the namespace or fix the source code and rebuild. 2) This will add to the baggage needed when you save() a nls fit in a workspace. I think that is inevitable as we cannot just identify the funtions used in the formula (as they might call other functions in the local environment), and it is necessary to capture the objects needed to evaluate the formula for the predict() method to be reliable. We could call all.names() to get the names of functions used directly in the formula, but that seems not good enough (previous para). Question to the cognescenti: is the price in 2) too great for this to be done for 1.9.1? I will put the change in R-devel for now. -- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595