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

John Fox j|ox @end|ng |rom mcm@@ter@c@
Sat Aug 13 20:27:39 CEST 2022


Dear John,

Please see below interline:

On 2022-08-13 1:15 p.m., J C Nash wrote:
> This posting is to answer "what I'm trying to do". Otherwise can be 
> skipped.
> 
> My nlsr package has a completely different structure (philosophy?) from 
> nls(). My aim is to
> try VERY hard to get solutions and not give up with "singular gradient" 
> or other issues as
> nls() does. But the package is quite lean and doesn't return a lot of 
> useful bits and pieces,
> such as nls returned functions and model stuff. So I've got a wrapnlsr() 
> function that runs my
> solver, then passes the best parameters to nls(). This won't always 
> work, for example, if
> the Jacobian at the best parameters is still singular, but very often it 
> will, and the
> wrapper then returns all the goodies and a user can use the output as 
> per nls().
> 
> Because my activities don't often get into those spin-offs of nls() -- 
> for instance the
> profile plots -- I really need some collaborators if nlsr is going to 
> get more capable in
> that regard. However, I feel the wrapper is at least a start.

If I understand correctly, there are two contexts here: (1) the 
interface for your wrapnlsr() function, and (2) how nlsr() calls other 
functions, including nls().

The first should probably work like a standard statistical modelling 
function, including how the weights argument is evaluated. The second is 
hidden from the user, and is where the scoping issue that you reported 
arose. My suggestion to follow a standard statistical modelling function 
here is probably off-base, and the previous two solutions, one from me 
and one from Noah, both work.

With respect to my solution: if you actually adopt it, I'd prefer not to 
use a name like data$weights, for fear of overwriting an existing 
variable in data called weights, but rather some like .weights or even 
..weights.. .

> 
> For anyone interested, I have been tightening up the nlsr package and 
> also trying to build a
> quite comprehensive collection of examples. Some areas of improvement 
> are in applying bounds
> and masks (fixed parameters) and using selfStart models. There is still 
> plenty to do, but the
> base package nlsr should be upgraded on CRAN in a few weeks. If anyone 
> is anxious to try it,
> let me know. The changes are mostly internal. The examples collection is 
> going to take a bit
> longer to get tidy, but I'll be happy to share those too. Material is on 
> Gitlab or Github,
> though definitely a work in progress and updated daily, often with loose 
> ends.

I'm probably the wrong person for this -- I'm familiar with nonlinear 
regression, but your knowledge of the computational details vastly 
exceeds mine.

> 
> Best, JN
> 
> PS. Why would we "evaluate" the weights? The nls() man-page says they 
> are fixed numbers, but
> the nls.R code I pointed to does evaluate them, and that seems to be the 
> trouble. Is that a bug?

What I meant by "evaluate" was associate a value with the symbol 
weights. The scoping issue was that nls() ended up looking in the global 
environment, where it found the weights() function rather than the local 
variable (i.e., argument) weights in your function.

Best,
  John

> 
> On 2022-08-13 12:58, John Fox wrote:
>> Dear John,
>>
>> After further thought, it's probably a better idea to evaluate the 
>> weights argument in the same environment as the formula rather than to 
>> bypass nonstandard evaluation. You could use lm() as a guide. I don't 
>> entirely understand what you're trying to do so maybe this suggestion 
>> is off-base.
>>
>> Best,
>>   John
>>
>> On 2022-08-13 9:41 a.m., J C Nash wrote:
>>>
>>> Thanks to John Fox and Noah Greifer. Both their approaches resolved 
>>> my immediate
>>> problem.
>>>
>>> That is, to provide a summary of the fix of my example code,
>>>
>>> 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)
>>> # Following fails -- closure error
>>> #  secondw<-nls(formula, data, firstcoef, control, algorithm=NULL, 
>>> TRUE, weights=weights)
>>> # from noah.greifer using gmail.com # this works OK
>>>    secondw <- do.call("nls", list(formula, data, firstcoef, control, 
>>> algorithm=NULL, TRUE, weights = weights))
>>> #  As does putting weights in the data dataframe (here not active)
>>> #  data$weights <- weights # from John Fox
>>> #  secondw<-nls(formula, data, firstcoef, control, algorithm=NULL, 
>>> TRUE, weights=weights)
>>>    secondw
>>> }
>>>
>>> Afraid I avoid the wonders of non-standard evaluation, and this time 
>>> it jumped up and bit me.
>>> But then I remember what machine instruction 260000800009 did on an 
>>> IBM 1620.
>>>
>>> The swiftness of reply from John and Noah was much appreciated.
>>>
>>> Best, JN
-- 
John Fox, Professor Emeritus
McMaster University
Hamilton, Ontario, Canada
web: https://socialsciences.mcmaster.ca/jfox/



More information about the R-package-devel mailing list