Search code examples
rconstraintsregressioncurve-fittingspline

Error with constrained curve fitting through specific points using the cobs package: NA/NaN/Inf in foreign function call


I'm trying to find the best fitting curve through a given set of points. The fitted curve must also pass through these points. I found an answer on Cross Validated which suggested to use the cobs: Constrained B-Splines (Sparse Matrix Based) package. However, I got an error while testing it with my sample data:

Error in x %*% coefficients: NA/NaN/Inf in foreign function call (arg 2)  

My question: what caused this error and how can I fix it? I'm open to other solutions using different methods/packages too. Thanks!

library(cobs)

dat <- data.frame(
  x = c(1e-06,0.25,0.5,0.75,1,2,3,4,5,6),
  y = c(1e-07,1.925,2.9625,3.469375,
        3.875,4.5315,4.89,5.09375,5.216,5.46))
dat
#>          x         y
#> 1  1.0e-06 0.0000001
#> 2  2.5e-01 1.9250000
#> 3  5.0e-01 2.9625000
#> 4  7.5e-01 3.4693750
#> 5  1.0e+00 3.8750000
#> 6  2.0e+00 4.5315000
#> 7  3.0e+00 4.8900000
#> 8  4.0e+00 5.0937500
#> 9  5.0e+00 5.2160000
#> 10 6.0e+00 5.4600000

# visual inspection
plot(dat); lines(dat)

# define constrained points
con <- matrix(
  cbind(c(0,0,0,0,0,0,0,0,0,0),
        c(1e-06,0.25,0.5,0.75,1,2,3, 4,5,6),
        c(1e-07,1.925,2.9625,3.469375,
          3.875,4.5315,4.89,5.09375,5.216, 5.46)), 
  ncol = 3, nrow = 10)

# curve fitting 
fit_result <- cobs(dat$x, dat$y, pointwise = con)
#> qbsks2():
#>  Performing general knot selection ...
#> Error in x %*% coefficients: NA/NaN/Inf in foreign function call (arg 2)

Created on 2020-01-21 by the reprex package (v0.3.0)


Solution

  • Note: I have answered this question on R-Help and the OP has asked me to also answer on SO.

    A solution is to explicitly set the type of constraint and choose a value for lambda. In a final mail, the OP gives extra information on how to fit the curve.

    library(cobs)
    
    dat <- data.frame(
      x = c(1e-06,0.25,0.5,0.75,1,2,3,4,5,6),
      y = c(1e-07,1.925,2.9625,3.469375,
            3.875,4.5315,4.89,5.09375,5.216,5.46))
    
    con <- matrix(
      cbind(c(0,0,0,0,0,0,0,0,0,0),
            c(1e-06,0.25,0.5,0.75,1,2,3, 4,5,6),
            c(1e-07,1.925,2.9625,3.469375,
              3.875,4.5315,4.89,5.09375,5.216, 5.46)),
      ncol = 3, nrow = 10)
    
    # curve fitting
    fit_result <- cobs(dat$x, dat$y,
                       constraint = "increase",
                       lambda = 0.1,
                       pointwise = con)
    
    pred <- predict(fit_result)
    
    plot(y~x, dat)
    lines(pred[,1], pred[,2], col = "red")
    

    enter image description here