[R] Error messages using nonlinear regression function (nls)

Martin Maechler
Fri, 20 Oct 2017 11:03:32 -0000

>>>>> PIKAL Petr <petr.pikal at precheza.cz>
>>>>>     on Fri, 20 Oct 2017 06:33:36 +0000 writes:

    > Hi
    > Keep your messages in the list, you increase your chance to get some
answer.

    > I changed your data to groupedData object (see below), but I did not
find any problem in it.

    > plot(wlg)
    > gives reasonable picture and I am not such expert to see any problem
with data. Seems to me, that something has to be wrong with nlsList function.

    >> wheat.list <- nlsList(Prop ~ SSlogis(end,Asym, xmid, scal),
data=wlg)
    > Warning message:
    > 6 times caught the same error in lm.fit(x, y, offset = offset,
singular.ok = singular.ok, ...): NA/NaN/Inf in 'x'

    > produces empty list. So maybe others could find some problem.

    > Cheers
    > Petr

Thank you, Petr,  for the reproducible example.

This indeed can be traced back to a bug in SSlogis() that has
been there since Doug Bates added the 'nls' package on Martin's
day 1999 (==> before R version 1.0.0 !) to R (svn rev 6455).

It's this part which does contain a thinko (by whomever, only
Doug may be able to remember/recall, but I guess it would have
been Jos? Pinheiro, then the grad student doing the nitty gritty),
I have added 2 '----------' below to make the 2 important lines stand
out :

   z <- xy[["y"]]
 ---------------------------------------------------------------------
   if (min(z) <= 0) { z <- z - 1.05 * min(z) } # avoid zeroes
   z <- z/(1.05 * max(z))		# scale to within unit height
 ---------------------------------------------------------------------
   xy[["z"]] <- log(z/(1 - z))		# logit transformation
   aux <- coef(lm(x ~ z, xy))

the first of the 2 lines,  commented   "avoid zeroes"
is obviously *not* avoiding zeroes in the case min(z) == 0 ,
and even though the 2 lines  should rescale an interval  [0, M]
to [eps, 1 - eps] they don't in this case.

Consequently, the next line  log(z/(1 - z))  transforms
the 0s into -Inf  and these lead to the warning (or error in nls())

  " NA/NaN/Inf in 'x' "

One could fix this up by  replacing  min(z)  by  min(z, -1e-7)
which may be best for pure back compatibility, but I really
don't like it either :

The famous  logit - transform   log( z / (1-z))
is really anti-symmetric around z = 1/2 , in particular should
treat 0 and 1 "symmetrically" and I find it ugly that
the previous fixup (our two ominous lines) is not at all
symmetric wrt 1/2, notably the 2nd transformation is made
unconditionally but the first one not.

Fortunately, the same source file, <R>/src/library/stats/R/zzzModels.R
also defines  the SSfpl()  == 4-parameter logistic model

and there, the 'init' function needs to do the same scaling to
(0, 1)  and does it much nicer, indeed (anti)symmetrically.

I'm looking into using that in SSlogis() as well,
fixing this bug.

Martin Maechler
ETH Zurich and R Core Team