fctbases vignette

Niels Olsen

3/12/2020

Easy-to-use, fast implementations of functional bases for use in functional data analysis and elsewhere.

fctbases is a package for R, which implements some of the common linear functional bases such as B-splines and Fourier bases and stores these internally as C++ objects, accesssed from R as normal functions. In this way there is no need for initializing an R object every time a basis is used in R. One simply initializes the desired basis, which is returned as an R function that one calls with desired time/evaluation points and possibly coefficients. All calculations are implemented in C++. By moving some of computations to the time when objects are initialized, this speeds up some of the computations the even more. The package takes care of the internal bookkeeping of C++ objects and ensures the validity of these.

First and second derivatives are also provided using the mathematical formulae for this. This is precise and uses no approximations.

Initializing a functional basis

Initialize a basis function by calling an appropiate initialization function, e.g.

knots <- 0:10 / 10

f <- make.bspline.basis(knots, order = 4)

will return a bspline of order 4 (standard) with equidistant knots from 0 to 1.

endpoints <- c(0, 1)

f <- make.fourier.basis(endpoints, 10)

will return a Fourier basis with harmonics up to order 10 (that is, 21 degress of freedom) anchored in 0 and 1.

Please see the help pages of the different functions for details.

Using a fctbasis function

After having generated a fctbasis object, it will return a function like this:

function (t, x, deriv = FALSE) 
{
    if (missing(x)) {
        if (deriv > 1L) 
            cpp_eval_D2(basis, t)
        else if (deriv) 
            cpp_eval_D(basis, t)
        else cpp_eval_0(basis, t)
    }
    else {
        if (deriv > 1L) 
            cpp_eval_D2_coefs(basis, t, x)
        else if (deriv) 
            cpp_eval_Dcoefs(basis, t, x)
        else cpp_eval_coefs(basis, t, x)
    }
}
<bytecode: 0x...>
<environment: 0x...>
attr(,"class")
[1] "fctbasis"

We see that this function (call it f) takes three arguments: t is a vector of evaluation points, x are optional coefficients to be multiplied, and deriv is whether the derivative (wrt. t) should be evaluated or not (defaults to false).

f(t): Returns a matrix of the basis function evaluted at time points t.

f(t, x): Returns a vector of the basis function evaluted at time points t, multiplied by coefficients x. Equal to f(t) %*% x

f(t, deriv = T): Returns first derivative, \(d/dt\) f(t).

f(t, x, deriv = T): Returns first derivative, \(d/dt\) f(t) %*% x.

f(t, deriv = 2): Returns second derivative, \({d^2}/ {dt^2}\) f(t).

f(t, x, deriv = 2): Returns second derivative, \(d^2 / dt^2\) f(t) %*% x.

Speed

A small code example with speed comparison

## Libraries
library(fctbases)
library(microbenchmark)
library(splines)
## Order 4 B-spline, 13 basis functions (10 intervals + 3)
knots <- 0:10 / 10

## the default way using splines::bs
bsb <- function(x) bs(x, knots = knots[2:10], Boundary.knots = c(knots[1], knots[11]), intercept = T)
## fctbases;
bf <- make.bspline.basis(knots = knots)

## some random coefficients and evaluation points
set.seed(3457)
coefs <- rnorm(13)
y <- sort(runif(100))


bf(0.3457)
##      [,1] [,2] [,3]       [,4]      [,5]      [,6]       [,7] [,8] [,9] [,10]
## [1,]    0    0    0 0.02668383 0.5055397 0.4518692 0.01590733    0    0     0
##      [,11] [,12] [,13]
## [1,]     0     0     0
bsb(0.3457)
##      1 2 3          4         5         6          7 8 9 10 11 12 13
## [1,] 0 0 0 0.02668383 0.5055397 0.4518692 0.01590733 0 0  0  0  0  0
## attr(,"degree")
## [1] 3
## attr(,"knots")
## [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
## attr(,"Boundary.knots")
## [1] 0 1
## attr(,"intercept")
## [1] TRUE
## attr(,"class")
## [1] "bs"     "basis"  "matrix"
microbenchmark(bf(y), bsb(y), times = 1000)
## Unit: microseconds
##    expr   min     lq     mean median     uq    max neval
##   bf(y)   6.1   8.15  10.5755    9.6  11.70   46.5  1000
##  bsb(y) 107.2 113.35 134.2470  122.7 131.75 3599.4  1000
microbenchmark(bf(y, coefs), bsb(y) %*% coefs, times = 1000)
## Unit: microseconds
##              expr   min    lq     mean median    uq    max neval
##      bf(y, coefs)   5.9   6.6   8.4749    8.3   9.0   77.3  1000
##  bsb(y) %*% coefs 109.3 115.3 129.7725  119.2 127.4 2237.6  1000

Installation

The package is available from CRAN: install.package("fctbases") or GitHub: “naolsen/fctbases”. The version on Github may be newer: download the source package or use devtools, e.g. devtools::install_github("naolsen/fctbases"). A C++ compiler is required to compile the source.

Issues

It is currently not possible to save fctbases objects as .RData objects (and likely will not be). Using a fctbasis object from a previous session will return an error.