[R] Error generated by nlme::gnls
Rolf Turner
r@turner @end|ng |rom @uck|@nd@@c@nz
Mon Jul 25 01:40:41 CEST 2022
On Sun, 24 Jul 2022 15:57:25 +0300
Ivan Krylov <krylov.r00t using gmail.com> wrote:
> Sorry for being too terse in my previous e-mail!
>
> On Sun, 24 Jul 2022 23:03:02 +1200
> Rolf Turner <r.turner using auckland.ac.nz> wrote:
>
> > The maintainer of the nlme package (who is, according to
> > maintainer(), "R-core") could change the code so that it uses
> > invokes deparse1() rather than deparse, but the user cannot do so,
> > not without in effect re-creating the package.
>
> You're right. I think there's a buglet in nlme::gnls that nobody
> noticed until R 4.2.0 was released *and* Aaron Crowley used the
> function with a sufficiently long formula.
Makes sense. :-)
> > Also, the question remains: why did Aaron Crowley's code work in
> > the past, whereas now it throws an error? What changed?
>
> gnls() may have been performing the `if (deparse(...) != '1')` test
> for a long time, but never crashed before because it wasn't a fatal
> error until R 4.2.0. Previously, if() would issue a warning and use
> the first element of the boolean vector.
N'ya-ha! Makes sense too.
>
> R 4.2.0 was released this April, which was less than 6 months ago. I
> think it all fits.
Indeed,
>
> A temporary solution would be to make use of the fact that R is a very
> dynamic language and perform surgery on a live function inside a
> loaded package:
>
> library(codetools)
>
> nlme <- loadNamespace('nlme')
> unlockBinding('gnls', nlme)
> nlme$gnls <- `body<-`(fun = nlme$gnls, value = walkCode(
> body(nlme$gnls), makeCodeWalker(
> call = function(e, w)
> as.call(lapply(as.list(e), function(ee)
> if (!missing(ee)) walkCode(ee, w)
> )),
> leaf = function(e, w)
> if (is.symbol(e) && e == 'deparse') {
> as.name('deparse1')
> } else e
> )
> ))
> lockBinding('gnls', nlme)
> rm(nlme)
>
> grep('deparse', deparse(nlme::gnls), value = TRUE)
> # [1] " deparse1(pp[[3]]), sep = \"~\"), collapse =
> \",\"), " # [2] " if (deparse1(params[[nm]][[3]]) != \"1\") {"
> # [3] " list(row.names(dataModShrunk), deparse1(form[[2]]))), "
>
> Aaron's example seems to work after this, modulo needing 12 starting
> values instead of 13.
Such surgery is beyond the capability of us ordinary mortals, but given
your explicit and clear recipe it should be do-able.
Thanks for all of this.
cheers,
Rolf
P. S. Ben: you were correct in your original conjecture, to which I
erroneously said "No". Lack of insight on my part.
R.
--
Honorary Research Fellow
Department of Statistics
University of Auckland
Phone: +64-9-373-7599 ext. 88276
More information about the R-help
mailing list