knitr::opts_chunk$set(comment = "", cache = TRUE) options(width = 100, digits = 5)
Package website: release | development
The R package splines2 is intended to be a user-friendly supplementary package to the base package splines.
The package splines2 provides functions to construct basis matrices of
In addition to the R interface, splines2 provides a C++ header-only library integrated with Rcpp, which allows the construction of spline basis functions directly in C++ with the help of Rcpp and RcppArmadillo. Thus, it can also be treated as one of the Rcpp* packages. A toy example package that uses the C++ interface is available here.
You can install the released version from CRAN.
install.packages("splines2")
The latest version of the package is under development at GitHub. If it is able to pass the automated package checks, one may install it by
if (! require(remotes)) install.packages("remotes") remotes::install_github("wenjie2wang/splines2", upgrade = "never")
The Online document provides a reference for all functions and contains the following vignettes:
Since v0.3.0, the implementation of the main functions has been rewritten in C++
with the help of the Rcpp and RcppArmadillo packages. The computational
performance has thus been boosted and comparable with the function
splines::splineDesign()
.
Some quick micro-benchmarks are provided below for reference.
library(microbenchmark) options(microbenchmark.unit="relative") library(splines) library(splines2) set.seed(123) x <- runif(1e3) degree <- 3 ord <- degree + 1 internal_knots <- seq.int(0.1, 0.9, 0.1) boundary_knots <- c(0, 1) all_knots <- sort(c(internal_knots, rep(boundary_knots, ord))) ## check equivalency of outputs my_check <- function(values) { all(sapply(values[- 1], function(x) { all.equal(unclass(values[[1]]), unclass(x), check.attributes = FALSE) })) }
For B-splines, function splines2::bSpline()
provides equivalent results with
splines::bs()
and splines::splineDesign()
, and is about 3x faster than
bs()
and 2x faster than splineDesign()
for this example.
## B-splines microbenchmark( "splines::bs" = bs(x, knots = internal_knots, degree = degree, intercept = TRUE, Boundary.knots = boundary_knots), "splines::splineDesign" = splineDesign(x, knots = all_knots, ord = ord), "splines2::bSpline" = bSpline( x, knots = internal_knots, degree = degree, intercept = TRUE, Boundary.knots = boundary_knots ), check = my_check )
Similarly, for derivatives of B-splines, splines2::dbs()
provides equivalent
results with splines::splineDesign()
, and is about 2x faster.
## Derivatives of B-splines derivs <- 2 microbenchmark( "splines::splineDesign" = splineDesign(x, knots = all_knots, ord = ord, derivs = derivs), "splines2::dbs" = dbs(x, derivs = derivs, knots = internal_knots, degree = degree, intercept = TRUE, Boundary.knots = boundary_knots), check = my_check )
The splines package does not contain an implementation for integrals of
B-splines. Thus, we performed a comparison with package ibs (version r
packageVersion("ibs")
), where the function ibs::ibs()
was also implemented in
Rcpp.
## integrals of B-splines set.seed(123) coef_sp <- rnorm(length(all_knots) - ord) microbenchmark( "ibs::ibs" = ibs::ibs(x, knots = all_knots, ord = ord, coef = coef_sp), "splines2::ibs" = as.numeric( splines2::ibs(x, knots = internal_knots, degree = degree, intercept = TRUE, Boundary.knots = boundary_knots) %*% coef_sp ), check = my_check )
The function ibs::ibs()
returns the integrated B-splines instead of the
integrals of spline basis functions. Thus, we applied the same coefficients to
the basis functions from splines2::ibs()
for equivalent results, which was
still much faster than ibs::ibs()
.
For natural cubic splines (based on B-splines), splines::ns()
uses the QR
decomposition to find the null space of the second derivatives of B-spline basis
functions at boundary knots, while splines2::nsp()
utilizes the
closed-form null space derived from the second derivatives of cubic B-splines,
which produces nonnegative basis functions (within boundary) and is more
computationally efficient.
microbenchmark( "splines::ns" = ns(x, knots = internal_knots, intercept = TRUE, Boundary.knots = boundary_knots), "splines2::nsp" = nsp( x, knots = internal_knots, intercept = TRUE, Boundary.knots = boundary_knots ) )
The functions bSpline()
and mSpline()
produce periodic spline basis
functions based on B-splines and M-splines, respectively, when periodic = TRUE
is specified.
The splines::periodicSpline()
returns a periodic interpolation spline (based
on B-splines) instead of basis matrix.
We performed a comparison with package pbs (version r packageVersion("pbs")
),
where the function pbs::pbs()
produces a basis matrix of periodic B-spline
by using splines::spline.des()
.
microbenchmark( "pbs::pbs" = pbs::pbs(x, knots = internal_knots, degree = degree, intercept = TRUE, periodic = TRUE, Boundary.knots = boundary_knots), "splines2::bSpline" = bSpline( x, knots = internal_knots, degree = degree, intercept = TRUE, Boundary.knots = boundary_knots, periodic = TRUE ), "splines2::mSpline" = mSpline( x, knots = internal_knots, degree = degree, intercept = TRUE, Boundary.knots = boundary_knots, periodic = TRUE ) )
Session Information for Benchmarks
sessionInfo()
GNU General Public License (≥ 3)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.