I am on the lookout for (an ideally inbuilt) function in Matlab that calculates a B spline basis matrix the same way as in R, e.g. for a spline basis with 20 equally spaced knots of degree 3, I would do in R
require(splines)
B = bs(x = seq(0,1,length.out=100),
knots = seq(0, 1, length.out=20), # 20 knots
degree = 3,
intercept = FALSE)
matplot(B,type="l")
To get the same in Matlab I thought I could use
B = spcol(linspace(0,1,20),3,linspace(0,1,100));
plot(B);
but as can be seen the boundary knots then are missing. Any thoughts what would be the equivalent syntax in Matlab to get the same as in R?
PS The code that R is using for bs()
is in somewhat simplified form:
basis <- function(x, degree, i, knots) {
if(degree == 0){
B <- ifelse((x >= knots[i]) & (x < knots[i+1]), 1, 0)
} else {
if((knots[degree+i] - knots[i]) == 0) {
alpha1 <- 0
} else {
alpha1 <- (x - knots[i])/(knots[degree+i] - knots[i])
}
if((knots[i+degree+1] - knots[i+1]) == 0) {
alpha2 <- 0
} else {
alpha2 <- (knots[i+degree+1] - x)/(knots[i+degree+1] - knots[i+1])
}
B <- alpha1*basis(x, (degree-1), i, knots) + alpha2*basis(x, (degree-1), (i+1), knots)
}
return(B)
}
bs <- function(x, degree=3, interior.knots=NULL, intercept=FALSE, Boundary.knots = c(0,1)) {
if(missing(x)) stop("You must provide x")
if(degree < 1) stop("The spline degree must be at least 1")
Boundary.knots <- sort(Boundary.knots)
interior.knots.sorted <- NULL
if(!is.null(interior.knots)) interior.knots.sorted <- sort(interior.knots)
knots <- c(rep(Boundary.knots[1], (degree+1)), interior.knots.sorted, rep(Boundary.knots[2], (degree+1)))
K <- length(interior.knots) + degree + 1
B.mat <- matrix(0,length(x),K)
for(j in 1:K) B.mat[,j] <- basis(x, degree, j, knots)
if(any(x == Boundary.knots[2])) B.mat[x == Boundary.knots[2], K] <- 1
if(intercept == FALSE) {
return(B.mat[,-1])
} else {
return(B.mat)
}
}