-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathcreate.bspline.basis.Rd
266 lines (249 loc) · 11.2 KB
/
create.bspline.basis.Rd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
\name{create.bspline.basis}
\alias{create.bspline.basis}
\title{
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
\code{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{
\item{rangeval}{
a numeric vector of length 2 defining the interval over which the
functional data object can be evaluated; default value is
\code{if(is.null(breaks)) 0:1 else range(breaks)}.
If \code{length(rangeval) == 1} and \code{rangeval <= 0}, this is an
error. Otherwise, if \code{length(rangeval) == 1}, \code{rangeval}
is replaced by \code{c(0,rangeval)}.
If length(rangeval)>2 and neither \code{breaks} nor \code{nbasis}
are provided, this extra long \code{rangeval} argument is assigned
to \code{breaks}, and then \code{rangeval = range(breaks)}.
NOTE: Nonnumerics are also accepted provided
\code{sum(is.na(as.numeric(rangeval))) == 0}. However, as of July
2, 2012, nonnumerics may not work for \code{argvals} in other
\code{fda} functions.
}
\item{nbasis}{
an integer variable specifying the number of basis functions. This
'nbasis' argument is ignored if \code{breaks} is supplied, in which
case
nbasis = nbreaks + norder - 2,
where nbreaks = length(breaks). If \code{breaks} is not supplied
and \code{nbasis} is, then
nbreaks = nbasis - norder + 2,
and breaks = seq(rangevals[1], rangevals[2], nbreaks).
}
\item{norder}{
an integer specifying the order of b-splines, which is one higher
than their degree. The default of 4 gives cubic splines.
}
\item{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 \code{breaks[1] = rangeval[1]} and
\code{breaks[nbreaks] = rangeval[2]}, where \code{nbreaks} is the
length of \code{breaks}. There must be at least 2 values in
\code{breaks}.
As for rangeval, must satisfy \code{sum(is.na(as.numeric(breaks)))
== 0}.
}
\item{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.
}
\item{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 \code{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.
}
\item{values}{
a list containing the basis functions and their derivatives
evaluated at the quadrature points contained in the first
column of \code{ quadvals }.
}
\item{basisvalues}{
a vector of lists, allocated by code such as \code{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
\code{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.
}
\item{names}{
either a character vector of the same length as the number of basis
functions or a single character string to which \code{norder, "."}
and \code{1:nbasis} are appended as \code{paste(names, norder, ".",
1:nbasis, sep="")}. For example, if \code{norder = 4}, this
defaults to \code{'bspl4.1', 'bspl4.2'}, ... .
}
}
\details{
Spline functions are constructed by joining polynomials end-to-end at
argument values called \emph{break points} or \emph{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 \emph{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:
\code{nbasis = norder + length(breaks) - 2}
The consistency of the values of \code{nbasis}, \code{norder} and
\code{breaks} is checked, and an error message results if this
equation is not satisfied.
\emph{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 \code{norder} replicates of the
end points rangeval. By contrast, the analogous functions
\link[splines]{splineDesign} and \link[splines]{spline.des} in the
\code{splines} package do NOT automatically replicate the end points.
To compare answers, the end knots must be replicated manually when
using \link[splines]{splineDesign} or \link[splines]{spline.des}.
}
\value{
a basis object of the type \code{bspline}
}
\references{
Ramsay, James O., Hooker, Giles, and Graves, Spencer (2009),
\emph{Functional data analysis with R and Matlab}, Springer, New
York.
Ramsay, James O., and Silverman, Bernard W. (2005), \emph{Functional
Data Analysis, 2nd ed.}, Springer, New York.
Ramsay, James O., and Silverman, Bernard W. (2002), \emph{Applied
Functional Data Analysis}, Springer, New York.
}
\seealso{
\code{\link{basisfd}},
\code{\link{create.constant.basis}},
\code{\link{create.exponential.basis}},
\code{\link{create.fourier.basis}},
\code{\link{create.monomial.basis}},
\code{\link{create.polygonal.basis}},
\code{\link{create.power.basis}}
\code{\link[splines]{splineDesign}}
\code{\link[splines]{spline.des}}
}
\examples{
##
## The simplest basis currently available with this function:
##
bspl1.1 <- create.bspline.basis(norder=1)
oldpar <- par(no.readonly=TRUE)
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)
\dontshow{stopifnot(}
all.equal(bspl1.1, b1.1)
\dontshow{)}
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)
par(oldpar)
}
% docclass is function
\keyword{smooth}