[R-pkg-devel] Strange behaviour of function called from within a function

Noah Greifer no@h@gre||er @end|ng |rom gm@||@com
Sat Aug 13 00:52:56 CEST 2022


This is an unfortunate problem caused by non-standard evaluation of the
`weights` argument. It happens with `lm()`, too. To solve it, you should
use do.call(), e.g.,

secondw <- do.call("nls", list(formula, data, firstcoef, control,
algorithm=NULL, TRUE, weights = weights))

The reason this works is that `weights` is evaluated in the `list()` call,
which uses standard evaluation, before being passed to `nls()`, rather than
in the `nls()` call. Using `alist()` instead, which doesn't evaluate its
arguments, creates the same problem. You unfortunately have to do this with
every function that involves nonstandard evaluation.

The error that you get, "invalid type (closure) for variable '(weights)'",
occurs because `nls()` is interpreting `weights` as the function
`weights()`, which is a closure (basically the same thing as a function),
rather than as the argument passed through the `weights` argument of
`tw()`.

Noah

On Fri, Aug 12, 2022 at 6:41 PM J C Nash <profjcnash using gmail.com> wrote:

> I have been trying to sort out an odd issue for the last few days in
> upgrading package
> nlsr (for nonlinear least squares). It generally does much better in
> finding solutions from
> poor starts than nls(), but it does not generate the full nls returned
> object. I've written a
> wrapper wrapnlsr() that calls my nlsr functions then uses the resulting
> parameters in nls()
> to get the nls object. But up to now, neither weights nor subset are
> allowed. I've not got
> to subset, but have been trying weights, with very strange results. The
> full example is too
> much code for the list, so I've faked the nlsr output as "firstcoef" in
> the example below.
> What is troubling is that a hand-run example "works", but using a function
> to do it fails
> when there are weights.
>
> The nls.R code referenced in the example around line 570 may suggest that
> its handling the
> weights may be the culprit here. I don't understand why
>      eval(substitute(weights), data, environment(formula))
> is needed for a fixed numeric vector of weights (as required by the
> manual).
>
> Any help welcome.
>
> John Nash
>
> The example:
>
> # wterr.R -- reproduce nls error when called from function
> rm(list=ls()) # probably not needed, but clear the workspace
>
> tnow <- function(formula, data, start, control, trace) {
>    firstcoef <- c(b1=199, b2=50, b3=0.3) # as if from another solver
>    cat("firstcoef:\n")
>    print(firstcoef)
>    cat("No weights\n")
>    second<-nls(formula, data, firstcoef, control, algorithm=NULL, TRUE)
>    second
> }
>
> tw <- function(formula, data, start, control, trace, weights) {
>    firstcoef <- c(b1=199, b2=50, b3=0.3)
>    cat("firstcoef:\n")
>    print(firstcoef)
>    cat("weights:"); print(weights)
>    secondw<-nls(formula, data, firstcoef, control, algorithm=NULL, TRUE,
> weights=weights)
>    secondw
> }
>
> weed <- c(5.308, 7.24, 9.638, 12.866, 17.069, 23.192, 31.443,
>            38.558, 50.156, 62.948, 75.995, 91.972)
> tt <- 1:12
> weeddf <- data.frame(tt, weed)
> hobbsu <- weed ~ b1/(1+b2*exp(-b3*tt))
> st2 <- c(b1=200, b2=50, b3=0.3)
> wts <- 0.5^tt # a straight scaling comes via wts <- rep(0.01, 12)
> # From this level, we can do the calculation
> firstcoef <- c(b1=199, b2=50, b3=0.3)
>
> # Does NOT work from the function tw with weights, but unweighted OK.
> # Is the issue line 570/571 of ./R-4.2.1/src/library/stats/R/nls.R ??
> tn2<-tnow(hobbsu, weeddf, st2, control=list(), trace=TRUE)
> tn2
> tt2<-tw(hobbsu, weeddf, st2, control=list(), trace=TRUE, weights=wts)
> tt2
>
> # But we can get it running directly
> formula<-hobbsu
> data<-weeddf
> control<-list()
> weights<-wts
> second<-nls(formula, data, firstcoef, control, algorithm=NULL, TRUE)
> second
> secondw<-nls(formula, data, firstcoef, control, algorithm=NULL, TRUE,
> weights=weights)
> secondw
> # And if we rerun the functions AFTER succeeding here, tw now works
> tn2<-tnow(hobbsu, weeddf, st2, control=list(), trace=TRUE)
> tn2
> tt2<-tw(hobbsu, weeddf, st2, control=list(), trace=TRUE, weights=wts)
> tt2
>
> ______________________________________________
> R-package-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>

	[[alternative HTML version deleted]]



More information about the R-package-devel mailing list