fda (version 5.1.9)

create.bspline.basis: Create a B-spline Basis

Description

Functional data objects are constructed by specifying a set of basis functions and a set of coefficients defining a linear combination of these basis functions. The B-spline basis is used for non-periodic functions. B-spline basis functions are polynomial segments jointed end-to-end at at argument values called knots, breaks or join points. The segments have specifiable smoothness across these breaks. B-spline basis functions have the advantages of very fast computation and great flexibility. A polygonal basis generated by create.polygonal.basis is essentially a B-spline basis of order 2, degree 1. Monomial and polynomial bases can be obtained as linear transformations of certain B-spline bases.

Usage

create.bspline.basis(rangeval=NULL, nbasis=NULL, norder=4,
      breaks=NULL, dropind=NULL, quadvals=NULL, values=NULL,
      basisvalues=NULL, names="bspl")

Arguments

rangeval

a numeric vector of length 2 defining the interval over which the functional data object can be evaluated; default value is if(is.null(breaks)) 0:1 else range(breaks).

If length(rangeval) == 1 and rangeval <= 0, this is an error. Otherwise, if length(rangeval) == 1, rangeval is replaced by c(0,rangeval).

If length(rangeval)>2 and neither breaks nor nbasis are provided, this extra long rangeval argument is assigned to breaks, and then rangeval = range(breaks).

NOTE: Nonnumerics are also accepted provided sum(is.na(as.numeric(rangeval))) == 0. However, as of July 2, 2012, nonnumerics may not work for argvals in other fda functions.

nbasis

an integer variable specifying the number of basis functions. This 'nbasis' argument is ignored if breaks is supplied, in which case

nbasis = nbreaks + norder - 2,

where nbreaks = length(breaks). If breaks is not supplied and nbasis is, then

nbreaks = nbasis - norder + 2,

and breaks = seq(rangevals[1], rangevals[2], nbreaks).

norder

an integer specifying the order of b-splines, which is one higher than their degree. The default of 4 gives cubic splines.

breaks

a vector specifying the break points defining the b-spline. Also called knots, these are a strictly increasing sequence of junction points between piecewise polynomial segments. They must satisfy breaks[1] = rangeval[1] and breaks[nbreaks] = rangeval[2], where nbreaks is the length of breaks. There must be at least 2 values in breaks.

As for rangeval, must satisfy sum(is.na(as.numeric(breaks))) == 0.

dropind

a vector of integers specifying the basis functions to be dropped, if any. For example, if it is required that a function be zero at the left boundary, this is achieved by dropping the first basis function, the only one that is nonzero at that point.

quadvals

a matrix with two columns and a number of rows equal to the number of quadrature points for numerical evaluation of the penalty integral. The first column of quadvals contains the quadrature points, and the second column the quadrature weights. A minimum of 5 values are required for each inter-knot interval, and that is often enough. For Simpson's rule, these points are equally spaced, and the weights are proportional to 1, 4, 2, 4, ..., 2, 4, 1.

values

a list containing the basis functions and their derivatives evaluated at the quadrature points contained in the first column of quadvals .

basisvalues

a vector of lists, allocated by code such as vector("list",1). This argument is designed to avoid evaluation of a basis system repeatedly at a set of argument values. Each list within the vector corresponds to a specific set of argument values, and must have at least two components, which may be tagged as you wish. The first component in an element of the list vector contains the argument values. The second component in an element of the list vector contains a matrix of values of the basis functions evaluated at the arguments in the first component. The third and subsequent components, if present, contain matrices of values their derivatives up to a maximum derivative order. Whenever function getbasismatrix() is called, it checks the first list in each row to see, first, if the number of argument values corresponds to the size of the first dimension, and if this test succeeds, checks that all of the argument values match. This takes time, of course, but is much faster than re-evaluation of the basis system.

names

either a character vector of the same length as the number of basis functions or a single character string to which norder, "." and 1:nbasis are appended as paste(names, norder, ".", 1:nbasis, sep=""). For example, if norder = 4, this defaults to 'bspl4.1', 'bspl4.2', ... .

Value

a basis object of the type bspline

Details

Spline functions are constructed by joining polynomials end-to-end at argument values called break points or knots. First, the interval is subdivided into a set of adjoining intervals separated the knots. Then a polynomial of order $m$ (degree $m-1$) is defined for each interval. To make the resulting piecewise polynomial smooth, two adjoining polynomials are constrained to have their values and all their derivatives up to order $m-2$ match at the point where they join.

Consider as an illustration the very common case where the order is 4 for all polynomials, so that degree of each polynomials is 3. That is, the polynomials are cubic. Then at each break point or knot, the values of adjacent polynomials must match, and so also for their first and second derivatives. Only their third derivatives will differ at the point of junction.

The number of degrees of freedom of a cubic spline function of this nature is calculated as follows. First, for the first interval, there are four degrees of freedom. Then, for each additional interval, the polynomial over that interval now has only one degree of freedom because of the requirement for matching values and derivatives. This means that the number of degrees of freedom is the number of interior knots (that is, not counting the lower and upper limits) plus the order of the polynomials:

nbasis = norder + length(breaks) - 2

The consistency of the values of nbasis, norder and breaks is checked, and an error message results if this equation is not satisfied.

B-splines are a set of special spline functions that can be used to construct any such piecewise polynomial by computing the appropriate linear combination. They derive their computational convenience from the fact that any B-spline basis function is nonzero over at most m adjacent intervals. The number of basis functions is given by the rule above for the number of degrees of freedom.

The number of intervals controls the flexibility of the spline; the more knots, the more flexible the resulting spline will be. But the position of the knots also plays a role. Where do we position the knots? There is room for judgment here, but two considerations must be kept in mind: (1) you usually want at least one argument value between two adjacent knots, and (2) there should be more knots where the curve needs to have sharp curvatures such as a sharp peak or valley or an abrupt change of level, but only a few knots are required where the curve is changing very slowly.

This function automatically includes norder replicates of the end points rangeval. By contrast, the analogous functions splineDesign and spline.des in the splines package do NOT automatically replicate the end points. To compare answers, the end knots must be replicated manually when using splineDesign or spline.des.

References

Ramsay, James O., Hooker, Giles, and Graves, Spencer (2009), Functional data analysis with R and Matlab, Springer, New York.

Ramsay, James O., and Silverman, Bernard W. (2005), Functional Data Analysis, 2nd ed., Springer, New York.

Ramsay, James O., and Silverman, Bernard W. (2002), Applied Functional Data Analysis, Springer, New York.

See Also

basisfd, create.constant.basis, create.exponential.basis, create.fourier.basis, create.monomial.basis, create.polygonal.basis, create.power.basis splineDesign spline.des

Examples

Run this code
# NOT RUN {
##
## The simplest basis currently available with this function:
##
bspl1.1 <- create.bspline.basis(norder=1)
plot(bspl1.1)
# 1 basis function, order 1 = degree 0 = step function:

# should be the same as above:
b1.1 <- create.bspline.basis(0:1, nbasis=1, norder=1, breaks=0:1)
# }
# NOT RUN {
all.equal(bspl1.1, b1.1)
# }
# NOT RUN {
bspl2.2 <- create.bspline.basis(norder=2)
plot(bspl2.2)

bspl3.3 <- create.bspline.basis(norder=3)
plot(bspl3.3)

bspl4.4 <- create.bspline.basis()
plot(bspl4.4)

bspl1.2 <- create.bspline.basis(norder=1, breaks=c(0,.5, 1))
plot(bspl1.2)
# 2 bases, order 1 = degree 0 = step functions:
# (1) constant 1 between 0 and 0.5 and 0 otherwise
# (2) constant 1 between 0.5 and 1 and 0 otherwise.

bspl2.3 <- create.bspline.basis(norder=2, breaks=c(0,.5, 1))
plot(bspl2.3)
# 3 bases:  order 2 = degree 1 = linear
# (1) line from (0,1) down to (0.5, 0), 0 after
# (2) line from (0,0) up to (0.5, 1), then down to (1,0)
# (3) 0 to (0.5, 0) then up to (1,1).

bspl3.4 <- create.bspline.basis(norder=3, breaks=c(0,.5, 1))
plot(bspl3.4)
# 4 bases:  order 3 = degree 2 = parabolas.
# (1) (x-.5)^2 from 0 to .5, 0 after
# (2) 2*(x-1)^2 from .5 to 1, and a parabola
#     from (0,0 to (.5, .5) to match
# (3 & 4) = complements to (2 & 1).

bSpl4. <- create.bspline.basis(c(-1,1))
plot(bSpl4.)
# Same as bSpl4.23 but over (-1,1) rather than (0,1).

# set up the b-spline basis for the lip data, using 23 basis functions,
#   order 4 (cubic), and equally spaced knots.
#  There will be 23 - 4 = 19 interior knots at 0.05, ..., 0.95
lipbasis <- create.bspline.basis(c(0,1), 23)
plot(lipbasis)

bSpl.growth <- create.bspline.basis(growth$age)
# cubic spline (order 4)

bSpl.growth6 <- create.bspline.basis(growth$age,norder=6)
# quintic spline (order 6)

##
## Nonnumeric rangeval
##

# Date
July4.1776 <- as.Date('1776-07-04')
Apr30.1789 <- as.Date('1789-04-30')
AmRev <- c(July4.1776, Apr30.1789)
BspRevolution <- create.bspline.basis(AmRev)

# POSIXct
July4.1776ct <- as.POSIXct1970('1776-07-04')
Apr30.1789ct <- as.POSIXct1970('1789-04-30')
AmRev.ct <- c(July4.1776ct, Apr30.1789ct)
BspRev.ct <- create.bspline.basis(AmRev.ct)

# }

Run the code above in your browser using DataCamp Workspace