wenjie2wang / splines2

Regression Spline Functions and Classes
https://wwenjie.org/splines2
GNU General Public License v3.0
42 stars 3 forks source link

issues with bSpline() and dbs() #2

Closed yao-yl closed 4 years ago

yao-yl commented 4 years ago

Hello, It seems the function bSpline() and dbs() require the x span larger than the span of knots. For example, the following design is OK in {splines},

x <- c(0.3,0.5,0.6)
knots <- c(0.2, 0.4, 0.7)
B <- splines::bs(x, knots = knots)

but returns errors in {splines2}

> B <- splines2::bSpline(x, knots = knots)
> output: Error in rcpp_bSpline_basis(x = xx, df = df, degree = degree, internal_knots = knots,  : 
  c++ exception (unknown reason)

Is there anyway to fix this?

wenjie2wang commented 4 years ago

Hi @yao-yl

The knots are internal knots. So they must be placed inside of the boundary knots, which are by default the range of x. You may explicitly specify Boundary.knots for boundary knots.

In your example, the B from splines::bs() had all zeros in its last column:

> B
     1          2         3         4     5 6
[1,] 1 0.00000000 0.0000000 0.0000000 0.000 0
[2,] 0 0.05555556 0.3055556 0.5138889 0.125 0
[3,] 0 0.00000000 0.0000000 0.0000000 1.000 0
attr(,"degree")
[1] 3
attr(,"knots")
[1] 0.2 0.4 0.7
attr(,"Boundary.knots")
[1] 0.3 0.6
attr(,"intercept")
[1] FALSE
attr(,"class")
[1] "bs"     "basis"  "matrix"

The boundary knots of B are c(0.3, 0.6). The "internal" knots 0.2 and 0.7 are actually placed outside of the boundary knots. It seems to be inappropriate:

> predict(B, seq.int(0, 1, 0.1))
       1             2            3             4     5   6
 [1,] 64 -8.400000e+01 2.400000e+01 -3.000000e+00 0.000   0
 [2,] 27 -3.355556e+01 8.444444e+00 -8.888889e-01 0.000   0
 [3,]  8 -8.444444e+00 1.555556e+00 -1.111111e-01 0.000   0
 [4,]  1  1.665335e-15 3.081488e-31  1.900633e-47 0.000   0
 [5,]  0  4.444444e-01 4.444444e-01  1.111111e-01 0.000   0
 [6,]  0  5.555556e-02 3.055556e-01  5.138889e-01 0.125   0
 [7,]  0  0.000000e+00          NaN           NaN   NaN NaN
 [8,]  0  0.000000e+00          NaN           NaN   NaN NaN
 [9,]  0  0.000000e+00          NaN           NaN   NaN NaN
[10,]  0  0.000000e+00          NaN           NaN   NaN NaN
[11,]  0  0.000000e+00          NaN           NaN   NaN NaN
attr(,"degree")
[1] 3
attr(,"knots")
[1] 0.2 0.4 0.7
attr(,"Boundary.knots")
[1] 0.3 0.6
attr(,"intercept")
[1] FALSE
attr(,"class")
[1] "bs"     "basis"  "matrix"
Warning message:
In bs(x = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),  :
  some 'x' values beyond boundary knots may cause ill-conditioned bases
yao-yl commented 4 years ago

Hi Wenjie, thanks for explanations! In particular I find the dbs() function very useful. Then I notice the higher order derivatives of the basis function can be very sensitive to the knots and boundary knots. Is there any general guidance for spline specification when the quantity of interest is the derivatives rather than the function per se?

wenjie2wang commented 4 years ago

Hi Yuling, you can probably try smoothing splines or penalized splines. For example, the stats::predict.smooth.spline has argument deriv for derivatives.