3

Why does ns(0.8) or ns(c(0.8)) return NA/NaN/Inf in foreign function call (arg 1)?

ns(c(0.8, 1.0)) works fine but I wonder why giving just 1 value to ns causes a NA/NaN/Inf in foreign function call (arg 1).

Example:

> library(splines)
> ns(0.8)
Error in qr.default(t(const)) : 
  NA/NaN/Inf in foreign function call (arg 1)


> ns(c(0.8, 1.0))
             1
[1,] 0.0000000
[2,] 0.8017837
attr(,"degree")
[1] 3
attr(,"knots")
numeric(0)
attr(,"Boundary.knots")
[1] 0.8 1.0
attr(,"intercept")
[1] FALSE
attr(,"class")
[1] "ns"     "basis"  "matrix"
Franck Dernoncourt
  • 77,520
  • 72
  • 342
  • 501
  • Can you explain how you think fitting a spline to one point _should_ work? `ns()` depends on the first argument insofar as it can be used to determine knot placement (including boundary knots). With only one data point, there is not enough information to make a sensible selection and it makes sense for the method to fail. – stephematician Jul 17 '17 at 09:39
  • @stephematician sounds like a better error message – Franck Dernoncourt Jul 17 '17 at 12:39

2 Answers2

3

EDIT: After a user comment, I realized my answer was irrelevant. However I'm not deleting it for now since I emailed the R-Core team about the (very real) discrepancy in the documentation and referred to this post in the email.


There is a discrepancy in the ns() function's documentation for the 2nd argument, df:

degrees of freedom. One can supply df rather than knots; ns() then chooses df - 1 - intercept knots at suitably chosen quantiles of x (which will ignore missing values). The default, df = 1, corresponds to no knots.

The actual default value is not 1, but NULL, as we can see in the Usage section:

ns(x, df = NULL, knots = NULL, intercept = FALSE, Boundary.knots = range(x))

Dominic Comtois
  • 10,230
  • 1
  • 39
  • 61
3

I agree the error message is not user friendly.. so a change seems rational at least for that. We have to look and see if ns(<1 number>), say ns(pi) can make sense at all... I'd rather discuss that on the R-devel mailing list (https://stat.ethz.ch/mailman/listinfo/r-devel) instead of here.

I also agree with @Dominic Comtois that the help page should be amended, as the default has not been 1 for a long time.

Last but not least, note that ns() and bs() should be considered as a pair as they were designed that way. As their main use had been in model formulas to generate a model.matrix(), I tend to agree that it would be nice if we can come up with a rational non-error result for the ns(pi) case. Thank you both for raising the issue!!

Martin Mächler
  • 4,619
  • 27
  • 27
  • As it happen this got me intrigued... and ... tada! .. I've improved R's `ns()` so that indeed it "now" (*) works to use `ns(pi)` notably it now will work to use `lm(y ~ x1 + ns(x2) + ..., data = myD)` even in the ("not so frequent" ;-) case where `myD` has only one observation. -- *) in R-devel for now, but I will port it to 'R 3.4.1 patched' too, so it will be in the next version of R. – Martin Mächler Jul 19 '17 at 08:15