splines2/ 0000755 0001762 0000144 00000000000 14470217507 012020 5 ustar ligges users splines2/NAMESPACE 0000644 0001762 0000144 00000002635 14423311457 013242 0 ustar ligges users # Generated by roxygen2: do not edit by hand
S3method("$",splines2)
S3method(deriv,BSpline)
S3method(deriv,BernsteinPoly)
S3method(deriv,CSpline)
S3method(deriv,ISpline)
S3method(deriv,MSpline)
S3method(deriv,NaturalSpline)
S3method(deriv,NaturalSplineK)
S3method(knots,splines2)
S3method(makepredictcall,BSpline)
S3method(makepredictcall,BernsteinPoly)
S3method(makepredictcall,CSpline)
S3method(makepredictcall,ISpline)
S3method(makepredictcall,MSpline)
S3method(makepredictcall,NaturalSpline)
S3method(makepredictcall,NaturalSplineK)
S3method(plot,splines2)
S3method(predict,BSpline)
S3method(predict,BernsteinPoly)
S3method(predict,CSpline)
S3method(predict,ISpline)
S3method(predict,MSpline)
S3method(predict,NaturalSpline)
S3method(predict,NaturalSplineK)
S3method(print,splines2)
S3method(update,BSpline)
S3method(update,BernsteinPoly)
S3method(update,CSpline)
S3method(update,ISpline)
S3method(update,MSpline)
S3method(update,NaturalSpline)
S3method(update,NaturalSplineK)
export(bSpline)
export(bernsteinPoly)
export(bpoly)
export(bsp)
export(cSpline)
export(csp)
export(dbs)
export(iSpline)
export(ibs)
export(isp)
export(mSpline)
export(msp)
export(naturalSpline)
export(nsk)
export(nsp)
importFrom(Rcpp,sourceCpp)
importFrom(graphics,abline)
importFrom(graphics,matplot)
importFrom(stats,deriv)
importFrom(stats,knots)
importFrom(stats,makepredictcall)
importFrom(stats,predict)
importFrom(stats,update)
useDynLib(splines2)
splines2/README.md 0000644 0001762 0000144 00000023426 14447616314 013311 0 ustar ligges users splines2
================
[](https://CRAN.R-project.org/package=splines2)
[](https://CRAN.R-project.org/package=splines2)
[](https://CRAN.R-project.org/package=splines2)
[](https://github.com/wenjie2wang/splines2/actions)
[](https://app.codecov.io/gh/wenjie2wang/splines2)
[](https://doi.org/10.6339/21-JDS1020)
**Package website**: [release](https://wwenjie.org/splines2) \|
[development](https://wwenjie.org/splines2/dev)
The R package **splines2** is intended to be a user-friendly
*supplementary* package to the base package **splines**.
## Features
The package **splines2** provides functions to construct basis matrices
of
- B-splines
- M-splines
- I-splines
- convex splines (C-splines)
- periodic splines
- natural cubic splines
- generalized Bernstein polynomials
- their integrals (except C-splines) and derivatives of given order by
closed-form recursive formulas
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](https://github.com/wenjie2wang/example-pkg-Rcpp-splines2).
## Installation of CRAN Version
You can install the released version from
[CRAN](https://CRAN.R-project.org/package=splines2).
``` r
install.packages("splines2")
```
## Development
The latest version of the package is under development at
[GitHub](https://github.com/wenjie2wang/splines2). If it is able to pass
the automated package checks, one may install it by
``` r
if (! require(remotes)) install.packages("remotes")
remotes::install_github("wenjie2wang/splines2", upgrade = "never")
```
## Getting Started
The [Online document](https://wwenjie.org/splines2) provides a reference
for all functions and contains the following vignettes:
- [Demonstration of the common usages in R through
examples](https://wwenjie.org/splines2/articles/splines2-intro).
- [Introduction to the usage with
Rcpp](https://wwenjie.org/splines2/articles/splines2-wi-rcpp)
## Performance
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.
``` r
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.
``` r
## 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
)
```
Unit: relative
expr min lq mean median uq max neval
splines::bs 3.7782 3.4316 3.1477 3.3053 2.7155 9.1782 100
splines::splineDesign 2.2235 1.9719 1.9135 2.1350 1.8306 2.3227 100
splines2::bSpline 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 100
Similarly, for derivatives of B-splines, `splines2::dbs()` provides
equivalent results with `splines::splineDesign()`, and is about 2x
faster.
``` r
## 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
)
```
Unit: relative
expr min lq mean median uq max neval
splines::splineDesign 2.6144 2.4443 2.1666 2.36 1.9582 1.7738 100
splines2::dbs 1.0000 1.0000 1.0000 1.00 1.0000 1.0000 100
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**.
``` r
## 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
)
```
Unit: relative
expr min lq mean median uq max neval
ibs::ibs 20.382 18.161 19.486 18.738 18.824 25.698 100
splines2::ibs 1.000 1.000 1.000 1.000 1.000 1.000 100
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.
``` r
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
)
)
```
Unit: relative
expr min lq mean median uq max neval
splines::ns 4.7595 4.4793 4.4742 4.3056 4.2125 6.0708 100
splines2::nsp 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 100
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 1.1),
where the function `pbs::pbs()` produces a basis matrix of periodic
B-spline by using `splines::spline.des()`.
``` r
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
)
)
```
Unit: relative
expr min lq mean median uq max neval
pbs::pbs 3.9822 3.9709 3.35972 3.9262 3.6969 1.26560 100
splines2::bSpline 1.0000 1.0000 1.00000 1.0000 1.0000 1.00000 100
splines2::mSpline 1.1411 1.1505 0.95812 1.1814 1.1423 0.12699 100
Session Information for Benchmarks
``` r
sessionInfo()
```
R version 4.3.1 (2023-06-16)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Arch Linux
Matrix products: default
BLAS/LAPACK: /usr/lib/libopenblas.so.0.3; LAPACK version 3.11.0
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8
[4] LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
time zone: America/New_York
tzcode source: system (glibc)
attached base packages:
[1] splines stats graphics grDevices utils datasets methods base
other attached packages:
[1] splines2_0.5.1.9000 microbenchmark_1.4.10
loaded via a namespace (and not attached):
[1] digest_0.6.31 codetools_0.2-19 ibs_1.4 fastmap_1.1.1 xfun_0.39
[6] pbs_1.1 knitr_1.43 htmltools_0.5.5 rmarkdown_2.21 cli_3.6.0
[11] compiler_4.3.1 tools_4.3.1 evaluate_0.21 Rcpp_1.0.10 yaml_2.3.7
[16] rlang_1.1.1
## License
[GNU General Public License](https://www.gnu.org/licenses/) (≥ 3)
splines2/man/ 0000755 0001762 0000144 00000000000 14412331615 012564 5 ustar ligges users splines2/man/predict.Rd 0000644 0001762 0000144 00000005416 14421235063 014513 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/predict.R
\name{predict}
\alias{predict}
\alias{predict.BSpline}
\alias{predict.MSpline}
\alias{predict.ISpline}
\alias{predict.CSpline}
\alias{predict.BernsteinPoly}
\alias{predict.NaturalSpline}
\alias{predict.NaturalSplineK}
\title{Compute Spline Function for Given Coefficients}
\usage{
\method{predict}{BSpline}(object, newx = NULL, coef = NULL, ...)
\method{predict}{MSpline}(object, newx = NULL, coef = NULL, ...)
\method{predict}{ISpline}(object, newx = NULL, coef = NULL, ...)
\method{predict}{CSpline}(object, newx = NULL, coef = NULL, ...)
\method{predict}{BernsteinPoly}(object, newx = NULL, coef = NULL, ...)
\method{predict}{NaturalSpline}(object, newx = NULL, coef = NULL, ...)
\method{predict}{NaturalSplineK}(object, newx = NULL, coef = NULL, ...)
}
\arguments{
\item{object}{Spline objects produced by the \code{splines2} package.}
\item{newx}{The \code{x} values at which evaluations are required. If it is
\code{NULL} (by default), the original \code{x} used to create the
spline object will be used.}
\item{coef}{A numeric vector specifying the coefficients of the spline basis
functions. If it is \code{NULL} (by default), the spline basis
functions will be returned. Otherwise, the resulting spline function
will be returned.}
\item{...}{Other options passed to the corresponding function that
constructs the input \code{object}. For example, the additional options
will be passed to \code{bSpline()} for a \code{BSpline} object.}
}
\value{
The function returns the spline basis functions with the new values
of \code{x} if \code{coef} is not specified. Otherwise, the function
returns the resulting spline function (or its derivative if
\code{derivs} is specified as a positive integer through \code{...}).
}
\description{
Returns the spline function (with the specified coefficients) or evaluate
the basis functions at the specified \code{x} if the coefficients are not
specified.
}
\examples{
library(splines2)
x <- seq.int(0, 1, 0.2)
knots <- c(0.3, 0.5, 0.6)
newx <- seq.int(0.1, 0.9, 0.2)
## Cubic B-spline basis functions
bs_mat <- bSpline(x, knots = knots)
## compute the B-spline basis functions at new x
predict(bs_mat, newx)
## compute the B-spline function for the specified coefficients
beta <- runif(ncol(bs_mat))
predict(bs_mat, coef = beta)
## compute the first derivative of the B-spline function
predict(bs_mat, coef = beta, derivs = 1)
## or equivalently
predict(deriv(bs_mat), coef = beta)
## compute the second derivative
predict(bs_mat, coef = beta, derivs = 2)
## or equivalently
predict(deriv(bs_mat, derivs = 2), coef = beta)
## compute the integral
predict(bs_mat, coef = beta, integral = TRUE)
## or equivalently
predict(update(bs_mat, integral = TRUE), coef = beta)
}
splines2/man/update.Rd 0000644 0001762 0000144 00000002357 14421235063 014344 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/update.R
\name{update}
\alias{update}
\alias{update.BSpline}
\alias{update.MSpline}
\alias{update.ISpline}
\alias{update.CSpline}
\alias{update.BernsteinPoly}
\alias{update.NaturalSpline}
\alias{update.NaturalSplineK}
\title{Update Spline Basis Functions}
\usage{
\method{update}{BSpline}(object, ...)
\method{update}{MSpline}(object, ...)
\method{update}{ISpline}(object, ...)
\method{update}{CSpline}(object, ...)
\method{update}{BernsteinPoly}(object, ...)
\method{update}{NaturalSpline}(object, ...)
\method{update}{NaturalSplineK}(object, ...)
}
\arguments{
\item{object}{Spline objects produced by the \code{splines2} package.}
\item{...}{Other arguments passed to the corresponing constructor function.}
}
\value{
An updated object of the same class as the input object with the
specified updates.
}
\description{
Update the knot placement, polynomial degree, and any other options
available when constructing the given spline object.
}
\examples{
library(splines2)
x <- seq.int(0, 1, 0.01)
knots <- c(0.3, 0.5, 0.6)
## quadratic B-splines
bsMat2 <- bSpline(x, knots = knots, degree = 2, intercept = TRUE)
## cubic B-splines
bsMat3 <- update(bsMat2, degree = 3)
}
splines2/man/plot.splines2.Rd 0000644 0001762 0000144 00000001667 14416140212 015574 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/plot.R
\name{plot.splines2}
\alias{plot.splines2}
\title{Visualize Spline Basis Functions}
\usage{
\method{plot}{splines2}(
x,
y,
from = NULL,
to = NULL,
n = 101,
mark_knots = c("none", "internal", "boundary", "all"),
...
)
}
\arguments{
\item{x}{A \code{splines2} object.}
\item{y}{An argument that is not used.}
\item{from, to}{Two numbers representing the start and end point for the
plot, respectively.}
\item{n}{An integer, the number of x values at which to evaluate.}
\item{mark_knots}{A character vector specifying if knot placement should be
indicated by vertical lines.}
\item{...}{Additional arguments (other than \code{x} and \code{y}) that
would be passed to \code{matplot()}.}
}
\description{
Plot spline basis functions by lines in different colors.
}
\details{
This function is intended to quickly visualize the spline basis functions.
}
splines2/man/splines2.Rd 0000644 0001762 0000144 00000003005 14470203365 014614 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/splines2-package.R
\docType{package}
\name{splines2}
\alias{splines2}
\alias{splines2-package}
\title{splines2: Regression Spline Functions and Classes}
\description{
This package provides functions to construct basis matrices of
\itemize{
\item B-splines
\item M-splines
\item I-splines
\item convex splines (C-splines)
\item periodic splines
\item natural cubic splines
\item generalized Bernstein polynomials
\item along with their integrals (except C-splines) and derivatives
of given order by closed-form recursive formulas
}
}
\details{
In addition to the R interface, it also provides a C++ header-only library
integrated with \pkg{Rcpp}, which allows the construction of spline basis
functions directly in C++ with the help of \pkg{Rcpp} and
\pkg{RcppArmadillo}. Thus, it can also be treated as one of the \pkg{Rcpp*}
packages. A toy example package that uses the C++ interface is available at
.
The package \pkg{splines2} is intended to be a user-friendly supplement to
the base package \pkg{splines}. The trailing number two in the package name
means "too" (and by no means refers to the generation two). See Wang and
Yan (2021) for details and illustrations of how the package can be applied
to shape-restricted regression.
}
\references{
Wang, W., & Yan, J. (2021). Shape-restricted regression splines with R
package \pkg{splines2}. \emph{Journal of Data Science}, 19(3), 498--517.
}
splines2/man/naturalSpline.Rd 0000644 0001762 0000144 00000016576 14447420257 015724 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/naturalSpline.R
\name{naturalSpline}
\alias{naturalSpline}
\alias{nsp}
\alias{nsk}
\title{Natural Cubic Spline Basis for Polynomial Splines}
\usage{
naturalSpline(
x,
df = NULL,
knots = NULL,
intercept = FALSE,
Boundary.knots = NULL,
trim = 0,
derivs = 0L,
integral = FALSE,
...
)
nsp(
x,
df = NULL,
knots = NULL,
intercept = FALSE,
Boundary.knots = NULL,
trim = 0,
derivs = 0L,
integral = FALSE,
...
)
nsk(
x,
df = NULL,
knots = NULL,
intercept = FALSE,
Boundary.knots = NULL,
trim = 0,
derivs = 0L,
integral = FALSE,
...
)
}
\arguments{
\item{x}{The predictor variable. Missing values are allowed and will be
returned as they are.}
\item{df}{Degree of freedom that equals to the column number of returned
matrix. One can specify \code{df} rather than \code{knots}, then the
function chooses \code{df - 1 - as.integer(intercept)} internal knots at
suitable quantiles of \code{x} ignoring missing values and those
\code{x} outside of the boundary. Thus, \code{df} must be greater than
or equal to \code{2}. If internal knots are specified via \code{knots},
the specified \code{df} will be ignored.}
\item{knots}{The internal breakpoints that define the splines. The default
is \code{NULL}, which results in a basis for ordinary polynomial
regression. Typical values are the mean or median for one knot,
quantiles for more knots. For periodic splines, the number of knots
must be greater or equal to the specified \code{degree - 1}.}
\item{intercept}{If \code{TRUE}, the complete basis matrix will be returned.
Otherwise, the first basis will be excluded from the output.}
\item{Boundary.knots}{Boundary points at which to anchor the splines. By
default, they are the range of \code{x} excluding \code{NA}. If both
\code{knots} and \code{Boundary.knots} are supplied, the basis
parameters do not depend on \code{x}. Data can extend beyond
\code{Boundary.knots}. For periodic splines, the specified bounary
knots define the cyclic interval.}
\item{trim}{The fraction (0 to 0.5) of observations to be trimmed from each
end of \code{x} before placing the default internal and boundary knots.
This argument will be ignored if \code{Boundary.knots} is specified.
The default value is \code{0} for backward compatibility, which sets the
boundary knots as the range of \code{x}. If a positive fraction is
specified, the default boundary knots will be equivalent to
\code{quantile(x, probs = c(trim, 1 - trim), na.rm = TRUE)}, which can
be a more sensible choice in practice due to the existence of outliers.
The default internal knots are placed within the boundary afterwards.}
\item{derivs}{A nonnegative integer specifying the order of derivatives of
natural splines. The default value is \code{0L} for the spline basis
functions.}
\item{integral}{A logical value. The default value is \code{FALSE}. If
\code{TRUE}, this function will return the integrated natural splines
from the left boundary knot.}
\item{...}{Optional arguments that are not used.}
}
\value{
A numeric matrix of \code{length(x)} rows and \code{df}
columns if \code{df} is specified or \code{length(knots) + 1 +
as.integer(intercept)} columns if \code{knots} are specified instead.
Attributes that correspond to the arguments specified are returned for
usage of other functions in this package.
}
\description{
Functions \code{naturalSpline()} and \code{nsk()} generate the natural cubic
spline basis functions, the corresponding derivatives or integrals (from the
left boundary knot). Both of them are different from \code{splines::ns()}.
However, for a given model fitting procedure, using different variants of
spline basis functions should result in identical prediction values. The
coefficient estimates of the spline basis functions returned by \code{nsk()}
are more interpretable compared to \code{naturalSpline()} or
\code{splines::ns()} .
}
\details{
The constructed spline basis functions from \code{naturalSpline()} are
nonnegative within boundary with the second derivatives being zeros at
boundary knots. The implementation utilizes the close-form null space that
can be derived from the recursive formula for the second derivatives of
B-splines. The function \code{nsp()} is an alias of \code{naturalSpline()}
to encourage the use in a model formula.
The function \code{nsk()} produces another variant of natural cubic spline
matrix such that only one of the basis functions is nonzero and takes a
value of one at every boundary and internal knot. As a result, the
coefficients of the resulting fit are the values of the spline function at
the knots, which makes it easy to interpret the coefficient estimates. In
other words, the coefficients of a linear model will be the heights of the
function at the knots if \code{intercept = TRUE}. If \code{intercept =
FALSE}, the coefficients will be the change in function value between each
knot. This implementation closely follows the function \code{nsk()} of the
\pkg{survival} package (version 3.2-8). The idea corresponds directly to
the physical implementation of a spline by passing a flexible strip of wood
or metal through a set of fixed points, which is a traditional way to create
smooth shapes for things like a ship hull.
The returned basis matrix can be obtained by transforming the corresponding
B-spline basis matrix with the matrix \code{H} provided in the attribute of
the returned object. Each basis is assumed to follow a linear trend for
\code{x} outside of boundary. A similar implementation is provided by
\code{splines::ns}, which uses QR decomposition to find the null space of
the second derivatives of B-spline basis at boundary knots. See
Supplementray Materials of Wang and Yan (2021) for a more detailed
introduction.
}
\examples{
library(splines2)
x <- seq.int(0, 1, 0.01)
knots <- c(0.3, 0.5, 0.6)
## naturalSpline()
nsMat0 <- naturalSpline(x, knots = knots, intercept = TRUE)
nsMat1 <- naturalSpline(x, knots = knots, intercept = TRUE, integral = TRUE)
nsMat2 <- naturalSpline(x, knots = knots, intercept = TRUE, derivs = 1)
nsMat3 <- naturalSpline(x, knots = knots, intercept = TRUE, derivs = 2)
op <- par(mfrow = c(2, 2), mar = c(2.5, 2.5, 0.2, 0.1), mgp = c(1.5, 0.5, 0))
plot(nsMat0, ylab = "basis")
plot(nsMat1, ylab = "integral")
plot(nsMat2, ylab = "1st derivative")
plot(nsMat3, ylab = "2nd derivative")
par(op) # reset to previous plotting settings
## nsk()
nskMat <- nsk(x, knots = knots, intercept = TRUE)
plot(nskMat, ylab = "nsk()", mark_knots = "all")
abline(h = 1, col = "red", lty = 3)
## use the deriv method
all.equal(nsMat0, deriv(nsMat1), check.attributes = FALSE)
all.equal(nsMat2, deriv(nsMat0))
all.equal(nsMat3, deriv(nsMat2))
all.equal(nsMat3, deriv(nsMat0, 2))
## a linear model example
fit1 <- lm(weight ~ -1 + nsk(height, df = 4, intercept = TRUE), data = women)
fit2 <- lm(weight ~ nsk(height, df = 3), data = women)
## the knots (same for both fits)
knots <- unlist(attributes(fit1$model[[2]])[c('Boundary.knots', 'knots')])
## predictions at the knot points
predict(fit1, data.frame(height = sort(unname(knots))))
unname(coef(fit1)) # equal to the coefficient estimates
## different interpretation when "intercept = FALSE"
unname(coef(fit1)[-1] - coef(fit1)[1]) # differences: yhat[2:4] - yhat[1]
unname(coef(fit2))[-1] # ditto
}
\seealso{
\code{\link{bSpline}} for B-splines;
\code{\link{mSpline}} for M-splines;
\code{\link{iSpline}} for I-splines.
}
splines2/man/deriv.Rd 0000644 0001762 0000144 00000006364 14421235063 014175 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deriv.R
\name{deriv}
\alias{deriv}
\alias{deriv.BSpline}
\alias{deriv.MSpline}
\alias{deriv.ISpline}
\alias{deriv.CSpline}
\alias{deriv.BernsteinPoly}
\alias{deriv.NaturalSpline}
\alias{deriv.NaturalSplineK}
\title{Derivatives of Spline Basis Functions}
\usage{
\method{deriv}{BSpline}(expr, derivs = 1L, ...)
\method{deriv}{MSpline}(expr, derivs = 1L, ...)
\method{deriv}{ISpline}(expr, derivs = 1L, ...)
\method{deriv}{CSpline}(expr, derivs = 1L, ...)
\method{deriv}{BernsteinPoly}(expr, derivs = 1L, ...)
\method{deriv}{NaturalSpline}(expr, derivs = 1L, ...)
\method{deriv}{NaturalSplineK}(expr, derivs = 1L, ...)
}
\arguments{
\item{expr}{Objects of class \code{bSpline2}, \code{ibs}, \code{mSpline},
\code{iSpline}, \code{cSpline}, \code{bernsteinPoly} or
\code{naturalSpline} with attributes describing \code{knots},
\code{degree}, etc.}
\item{derivs}{A positive integer specifying the order of derivatives. By
default, it is \code{1L} for the first derivatives.}
\item{...}{Optional arguments that are not used.}
}
\value{
A numeric matrix of the same dimension with the input \code{expr}.
}
\description{
Returns derivatives of given order for the given spline basis functions.
}
\details{
At knots, the derivative is defined to be the right derivative except at the
right boundary knot. By default, the function returns the first derivatives.
For derivatives of order greater than one, nested function calls such as
\code{deriv(deriv(expr))} are supported but not recommended. For a better
performance, argument \code{derivs} should be specified instead.
This function is designed for objects produced by this package. It
internally extracts necessary specification about the spline/polynomial
basis matrix from its attributes. Therefore, the function will not work if
the key attributes are not available after some operations.
}
\examples{
library(splines2)
x <- c(seq.int(0, 1, 0.1), NA) # NA's will be kept.
knots <- c(0.3, 0.5, 0.6)
## helper function
stopifnot_equivalent <- function(...) {
stopifnot(all.equal(..., check.attributes = FALSE))
}
## integal of B-splines and the corresponding B-splines integrated
ibsMat <- ibs(x, knots = knots)
bsMat <- bSpline(x, knots = knots)
## the first derivative
d1Mat <- deriv(ibsMat)
stopifnot_equivalent(bsMat, d1Mat)
## the second derivative
d2Mat1 <- deriv(bsMat)
d2Mat2 <- deriv(ibsMat, derivs = 2L)
stopifnot_equivalent(d2Mat1, d2Mat2)
## nested calls are supported
d2Mat3 <- deriv(deriv(ibsMat))
stopifnot_equivalent(d2Mat2, d2Mat3)
## C-splines, I-splines, M-splines and the derivatives
csMat <- cSpline(x, knots = knots, intercept = TRUE, scale = FALSE)
isMat <- iSpline(x, knots = knots, intercept = TRUE)
stopifnot_equivalent(isMat, deriv(csMat))
msMat <- mSpline(x, knots = knots, intercept = TRUE)
stopifnot_equivalent(msMat, deriv(isMat))
stopifnot_equivalent(msMat, deriv(csMat, 2))
stopifnot_equivalent(msMat, deriv(deriv(csMat)))
dmsMat <- mSpline(x, knots = knots, intercept = TRUE, derivs = 1)
stopifnot_equivalent(dmsMat, deriv(msMat))
stopifnot_equivalent(dmsMat, deriv(isMat, 2))
stopifnot_equivalent(dmsMat, deriv(deriv(isMat)))
stopifnot_equivalent(dmsMat, deriv(csMat, 3))
stopifnot_equivalent(dmsMat, deriv(deriv(deriv(csMat))))
}
splines2/man/cSpline.Rd 0000644 0001762 0000144 00000012204 14441405225 014450 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/cSpline.R
\name{cSpline}
\alias{cSpline}
\alias{csp}
\title{C-Spline Basis for Polynomial Splines}
\usage{
cSpline(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = TRUE,
Boundary.knots = NULL,
derivs = 0L,
scale = TRUE,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
csp(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = TRUE,
Boundary.knots = NULL,
derivs = 0L,
scale = TRUE,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
}
\arguments{
\item{x}{The predictor variable. Missing values are allowed and will be
returned as they are.}
\item{df}{Degree of freedom that equals to the column number of the returned
matrix. One can specify \code{df} rather than \code{knots}, then the
function chooses \code{df - degree - as.integer(intercept)} internal
knots at suitable quantiles of \code{x} ignoring missing values and
those \code{x} outside of the boundary. For periodic splines, \code{df
- as.integer(intercept)} internal knots will be chosen at suitable
quantiles of \code{x} relative to the beginning of the cyclic intervals
they belong to (see Examples) and the number of internal knots must be
greater or equal to the specified \code{degree - 1}. If internal knots
are specified via \code{knots}, the specified \code{df} will be ignored.}
\item{knots}{The internal breakpoints that define the splines. The default
is \code{NULL}, which results in a basis for ordinary polynomial
regression. Typical values are the mean or median for one knot,
quantiles for more knots. For periodic splines, the number of knots
must be greater or equal to the specified \code{degree - 1}.}
\item{degree}{The degree of C-spline defined to be the degree of the
associated M-spline instead of actual polynomial degree. For example,
C-spline basis of degree 2 is defined as the scaled double integral of
associated M-spline basis of degree 2.}
\item{intercept}{If \code{TRUE} by default, all of the spline basis
functions are returned. Notice that when using C-Spline for
shape-restricted regression, \code{intercept = TRUE} should be set even
when an intercept term is considered additional to the spline basis in
the model.}
\item{Boundary.knots}{Boundary points at which to anchor the splines. By
default, they are the range of \code{x} excluding \code{NA}. If both
\code{knots} and \code{Boundary.knots} are supplied, the basis
parameters do not depend on \code{x}. Data can extend beyond
\code{Boundary.knots}. For periodic splines, the specified bounary
knots define the cyclic interval.}
\item{derivs}{A nonnegative integer specifying the order of derivatives of
C-splines. The default value is \code{0L} for C-spline basis functions.}
\item{scale}{A logical value indicating if scaling C-splines is required. If
\code{TRUE} by default, each C-spline basis is scaled to have unit
height at right boundary knot. The corresponding I-spline and M-spline
produced by \code{deriv} methods will be scaled to the same extent.}
\item{warn.outside}{A logical value indicating if a warning should be thrown
out when any \code{x} is outside the boundary. This option can also be
set through \code{options("splines2.warn.outside")} after the package is
loaded.}
\item{...}{Optional arguments that are not used.}
}
\value{
A numeric matrix of \code{length(x)} rows and \code{df} columns if
\code{df} is specified. If \code{knots} are specified instead, the
output matrix will consist of \code{length(knots) + degree +
as.integer(intercept)} columns. Attributes that correspond to the
arguments specified are returned for usage of other functions in this
package.
}
\description{
Generates the convex regression spline (called C-spline) basis matrix by
integrating I-spline basis for a polynomial spline or the corresponding
derivatives.
}
\details{
It is an implementation of the closed-form C-spline basis derived from the
recursion formula of I-splines and M-splines. The function \code{csp()} is
an alias of to encourage the use in a model formula.
}
\examples{
library(splines2)
x <- seq.int(0, 1, 0.01)
knots <- c(0.3, 0.5, 0.6)
### when 'scale = TRUE' (by default)
csMat <- cSpline(x, knots = knots, degree = 2)
plot(csMat, ylab = "C-spline basis", mark_knots = "internal")
isMat <- deriv(csMat)
msMat <- deriv(csMat, derivs = 2)
plot(isMat, ylab = "scaled I-spline basis")
plot(msMat, ylab = "scaled M-spline basis")
### when 'scale = FALSE'
csMat <- cSpline(x, knots = knots, degree = 2, scale = FALSE)
## the corresponding I-splines and M-splines (with same arguments)
isMat <- iSpline(x, knots = knots, degree = 2)
msMat <- mSpline(x, knots = knots, degree = 2, intercept = TRUE)
## or using deriv methods (more efficient)
isMat1 <- deriv(csMat)
msMat1 <- deriv(csMat, derivs = 2)
## equivalent
stopifnot(all.equal(isMat, isMat1, check.attributes = FALSE))
stopifnot(all.equal(msMat, msMat1, check.attributes = FALSE))
}
\references{
Meyer, M. C. (2008). Inference using shape-restricted regression splines.
\emph{The Annals of Applied Statistics}, 2(3), 1013--1033.
}
\seealso{
\code{\link{iSpline}} for I-splines;
\code{\link{mSpline}} for M-splines.
}
splines2/man/knots.Rd 0000644 0001762 0000144 00000002167 14271262203 014216 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/knots.R
\name{knots}
\alias{knots}
\alias{knots.splines2}
\title{Extract Knots from the Given Object}
\usage{
\method{knots}{splines2}(Fn, type = c("internal", "boundary"), ...)
}
\arguments{
\item{Fn}{An \code{splines2} object produced by this package.}
\item{type}{A character vector of length one indicating the type of knots to
return. The available choices are \code{"internal"} for internal knots
and \code{"Boundary"} for boundary knots.}
\item{...}{Optional arguments that are not used now.}
}
\value{
A numerical vector.
}
\description{
Methods for the generic function \code{knots} from the \pkg{stats} package
to obtain internal or boundary knots from the objects produced by this
package.
}
\examples{
library(splines2)
set.seed(123)
x <- rnorm(100)
## B-spline basis
bsMat <- bSpline(x, df = 8, degree = 3)
## extract internal knots placed based on the quantile of x
(internal_knots <- knots(bsMat))
## extract boundary knots placed based on the range of x
boundary_knots <- knots(bsMat, type = "boundary")
all.equal(boundary_knots, range(x))
}
splines2/man/bernsteinPoly.Rd 0000644 0001762 0000144 00000006071 14441405225 015715 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bernsteinPoly.R
\name{bernsteinPoly}
\alias{bernsteinPoly}
\alias{bpoly}
\title{Generalized Bernstein Polynomial Basis Functions}
\usage{
bernsteinPoly(
x,
degree = 3,
intercept = FALSE,
Boundary.knots = NULL,
derivs = 0L,
integral = FALSE,
...
)
bpoly(
x,
degree = 3,
intercept = FALSE,
Boundary.knots = NULL,
derivs = 0L,
integral = FALSE,
...
)
}
\arguments{
\item{x}{The predictor variable taking values inside of the specified
boundary. Missing values are allowed and will be returned as they are.}
\item{degree}{A nonnegative integer representing the degree of the
polynomials.}
\item{intercept}{If \code{TRUE}, the complete basis matrix will be returned.
Otherwise, the first basis will be excluded from the output.}
\item{Boundary.knots}{Boundary points at which to anchor the Bernstein
polynomial basis. The default value is \code{NULL} and the boundary
knots is set internally to be \code{range(x, na.rm = TRUE)}.}
\item{derivs}{A nonnegative integer specifying the order of derivatives.
The default value is \code{0L} for Bernstein polynomial basis functions.}
\item{integral}{A logical value. If \code{TRUE}, the integrals of the
Bernstein polynomials will be returned. The default value is
\code{FALSE}.}
\item{...}{Optional arguments that are not used.}
}
\value{
A \code{BernsteinPoly} object that is essentially a numeric matrix
of dimension \code{length(x)} by \code{degree + as.integer(intercept)}.
}
\description{
Returns generalized Bernstein polynomial basis functions of the given degree
over the specified range.
}
\details{
The Bernstein polynomial basis functions are defined over the support from 0
to 1. The generalized Bernstein polynomial basis functions extend the
support to any finite interval in the real line.
The function \code{bpoly()} is an alias to encourage the use in a model
formula.
}
\examples{
library(splines2)
x1 <- seq.int(0, 1, 0.01)
x2 <- seq.int(- 2, 2, 0.01)
## Bernstein polynomial basis matrix over [0, 1]
bMat1 <- bernsteinPoly(x1, degree = 4, intercept = TRUE)
## generalized Bernstein polynomials basis over [- 2, 2]
bMat2 <- bernsteinPoly(x2, degree = 4, intercept = TRUE)
op <- par(mfrow = c(1, 2))
plot(bMat1)
plot(bMat2)
## the first and second derivative matrix
d1Mat1 <- bernsteinPoly(x1, degree = 4, derivs = 1, intercept = TRUE)
d2Mat1 <- bernsteinPoly(x1, degree = 4, derivs = 2, intercept = TRUE)
d1Mat2 <- bernsteinPoly(x2, degree = 4, derivs = 1, intercept = TRUE)
d2Mat2 <- bernsteinPoly(x2, degree = 4, derivs = 2, intercept = TRUE)
par(mfrow = c(2, 2))
plot(d1Mat1)
plot(d1Mat2)
plot(d2Mat1)
plot(d2Mat2)
## reset to previous plotting settings
par(op)
## or use the deriv method
all.equal(d1Mat1, deriv(bMat1))
all.equal(d2Mat1, deriv(bMat1, 2))
## the integrals
iMat1 <- bernsteinPoly(x1, degree = 4, integral = TRUE, intercept = TRUE)
iMat2 <- bernsteinPoly(x2, degree = 4, integral = TRUE, intercept = TRUE)
all.equal(deriv(iMat1), bMat1, check.attributes = FALSE)
all.equal(deriv(iMat2), bMat2, check.attributes = FALSE)
}
splines2/man/bSpline.Rd 0000644 0001762 0000144 00000015226 14447611271 014464 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/bSpline.R
\name{bSpline}
\alias{bSpline}
\alias{ibs}
\alias{dbs}
\alias{bsp}
\title{B-Spline Basis for Polynomial Splines}
\usage{
bSpline(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = FALSE,
Boundary.knots = NULL,
periodic = FALSE,
derivs = 0L,
integral = FALSE,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
ibs(
x,
df = NULL,
knots = NULL,
degree = 3,
intercept = FALSE,
Boundary.knots = NULL,
...
)
dbs(
x,
derivs = 1L,
df = NULL,
knots = NULL,
degree = 3,
intercept = FALSE,
Boundary.knots = NULL,
...
)
bsp(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = FALSE,
Boundary.knots = NULL,
periodic = FALSE,
derivs = 0L,
integral = FALSE,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
}
\arguments{
\item{x}{The predictor variable. Missing values are allowed and will be
returned as they are.}
\item{df}{Degree of freedom that equals to the column number of the returned
matrix. One can specify \code{df} rather than \code{knots}, then the
function chooses \code{df - degree - as.integer(intercept)} internal
knots at suitable quantiles of \code{x} ignoring missing values and
those \code{x} outside of the boundary. For periodic splines, \code{df
- as.integer(intercept)} internal knots will be chosen at suitable
quantiles of \code{x} relative to the beginning of the cyclic intervals
they belong to (see Examples) and the number of internal knots must be
greater or equal to the specified \code{degree - 1}. If internal knots
are specified via \code{knots}, the specified \code{df} will be ignored.}
\item{knots}{The internal breakpoints that define the splines. The default
is \code{NULL}, which results in a basis for ordinary polynomial
regression. Typical values are the mean or median for one knot,
quantiles for more knots. For periodic splines, the number of knots
must be greater or equal to the specified \code{degree - 1}.}
\item{degree}{A nonnegative integer specifying the degree of the piecewise
polynomial. The default value is \code{3} for cubic splines. Zero degree
is allowed for piecewise constant basis functions.}
\item{intercept}{If \code{TRUE}, the complete basis matrix will be returned.
Otherwise, the first basis will be excluded from the output.}
\item{Boundary.knots}{Boundary points at which to anchor the splines. By
default, they are the range of \code{x} excluding \code{NA}. If both
\code{knots} and \code{Boundary.knots} are supplied, the basis
parameters do not depend on \code{x}. Data can extend beyond
\code{Boundary.knots}. For periodic splines, the specified bounary
knots define the cyclic interval.}
\item{periodic}{A logical value. If \code{TRUE}, the periodic splines will
be returned. The default value is \code{FALSE}.}
\item{derivs}{A nonnegative integer specifying the order of derivatives of
splines basis function. The default value is \code{0}.}
\item{integral}{A logical value. If \code{TRUE}, the corresponding
integrals of spline basis functions will be returned. The default value
is \code{FALSE}. For periodic splines, the integral of each basis is
integrated from the left boundary knot.}
\item{warn.outside}{A logical value indicating if a warning should be thrown
out when any \code{x} is outside the boundary. This option can also be
set through \code{options("splines2.warn.outside")} after the package is
loaded.}
\item{...}{Optional arguments that are not used.}
}
\value{
A numeric matrix of \code{length(x)} rows and \code{df} columns if
\code{df} is specified. If \code{knots} are specified instead, the
output matrix will consist of \code{length(knots) + degree +
as.integer(intercept)} columns if \code{periodic = FALSE}, or
\code{length(knots) + as.integer(intercept)} columns if \code{periodic =
TRUE}. Attributes that correspond to the arguments specified are
returned for usage of other functions in this package.
}
\description{
Generates the spline basis matrix for B-splines representing the family of
piecewise polynomials with the specified interior knots, degree, and
boundary knots, evaluated at the values of \code{x}.
}
\details{
This function extends the \code{bs()} function in the \code{splines} package
for B-spline basis functions by allowing piecewise constant (left-closed and
right-open except on the right boundary) spline basis of degree zero. In
addition, the function provides derivatives or integrals of the B-spline
basis functions when one specifies the arguments \code{derivs} or
\code{integral} appropriately. The function constructs periodic B-splines
when \code{periodic} is \code{TRUE}. All the implementations are based on
the closed-form recursion formula following De Boor (1978) and Wang and Yan
(2021).
The functions \code{ibs()} and \code{dbs()} are provided for convenience.
The former provides the integrals of B-splines and is equivalent to
\code{bSpline()} with \code{integral = TRUE}. The latter produces the
derivatives of given order of B-splines and is equivalent to
\code{bSpline()} with default \code{derivs = 1}. The function \code{bsp()}
is an alias of to encourage the use in a model formula.
}
\examples{
library(splines2)
set.seed(1)
x <- runif(100)
knots <- c(0.3, 0.5, 0.6) # internal knots
## cubic B-splines
bsMat <- bSpline(x, knots = knots, degree = 3, intercept = TRUE)
ibsMat <- update(bsMat, integral = TRUE) # the integrals
d1Mat <- deriv(bsMat) # the 1st derivaitves
d2Mat <- deriv(bsMat, 2) # the 2nd derivaitves
op <- par(mfrow = c(2, 2), mar = c(2.5, 2.5, 0.2, 0.1), mgp = c(1.5, 0.5, 0))
plot(bsMat, ylab = "Cubic B-splines")
plot(ibsMat, ylab = "The integrals")
plot(d1Mat, ylab = "The 1st derivatives")
plot(d2Mat, ylab = "The 2nd derivatives")
## evaluate at new values
predict(bsMat, c(0.125, 0.801))
## periodic B-splines
px <- seq(0, 3, 0.01)
pbsMat <- bSpline(px, knots = knots, Boundary.knots = c(0, 1),
intercept = TRUE, periodic = TRUE)
ipMat <- update(pbsMat, integral = TRUE)
dpMat <- deriv(pbsMat)
dp2Mat <- deriv(pbsMat, 2)
plot(pbsMat, ylab = "Periodic B-splines", mark_knots = "b")
plot(ipMat, ylab = "The integrals", mark_knots = "b")
plot(dpMat, ylab = "The 1st derivatives", mark_knots = "b")
plot(dp2Mat, ylab = "The 2nd derivatives", mark_knots = "b")
par(op) # reset to previous plotting settings
}
\references{
De Boor, Carl. (1978). \emph{A practical guide to splines}.
Vol. 27. New York: Springer-Verlag.
Wang, W., & Yan, J. (2021). \emph{Shape-restricted regression splines with R
package splines2}. Journal of Data Science, 19(3),498--517.
}
\seealso{
\code{\link{knots}} for extracting internal and boundary knots.
}
splines2/man/iSpline.Rd 0000644 0001762 0000144 00000010545 14441405225 014464 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/iSpline.R
\name{iSpline}
\alias{iSpline}
\alias{isp}
\title{I-Spline Basis for Polynomial Splines}
\usage{
iSpline(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = TRUE,
Boundary.knots = NULL,
derivs = 0L,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
isp(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = TRUE,
Boundary.knots = NULL,
derivs = 0L,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
}
\arguments{
\item{x}{The predictor variable. Missing values are allowed and will be
returned as they are.}
\item{df}{Degree of freedom that equals to the column number of the returned
matrix. One can specify \code{df} rather than \code{knots}, then the
function chooses \code{df - degree - as.integer(intercept)} internal
knots at suitable quantiles of \code{x} ignoring missing values and
those \code{x} outside of the boundary. For periodic splines, \code{df
- as.integer(intercept)} internal knots will be chosen at suitable
quantiles of \code{x} relative to the beginning of the cyclic intervals
they belong to (see Examples) and the number of internal knots must be
greater or equal to the specified \code{degree - 1}. If internal knots
are specified via \code{knots}, the specified \code{df} will be ignored.}
\item{knots}{The internal breakpoints that define the splines. The default
is \code{NULL}, which results in a basis for ordinary polynomial
regression. Typical values are the mean or median for one knot,
quantiles for more knots. For periodic splines, the number of knots
must be greater or equal to the specified \code{degree - 1}.}
\item{degree}{The degree of I-spline defined to be the degree of the
associated M-spline instead of actual polynomial degree. For example,
I-spline basis of degree 2 is defined as the integral of associated
M-spline basis of degree 2.}
\item{intercept}{If \code{TRUE} by default, all of the spline basis
functions are returned. Notice that when using I-Spline for monotonic
regression, \code{intercept = TRUE} should be set even when an intercept
term is considered additional to the spline basis functions.}
\item{Boundary.knots}{Boundary points at which to anchor the splines. By
default, they are the range of \code{x} excluding \code{NA}. If both
\code{knots} and \code{Boundary.knots} are supplied, the basis
parameters do not depend on \code{x}. Data can extend beyond
\code{Boundary.knots}. For periodic splines, the specified bounary
knots define the cyclic interval.}
\item{derivs}{A nonnegative integer specifying the order of derivatives of
I-splines.}
\item{warn.outside}{A logical value indicating if a warning should be thrown
out when any \code{x} is outside the boundary. This option can also be
set through \code{options("splines2.warn.outside")} after the package is
loaded.}
\item{...}{Optional arguments that are not used.}
}
\value{
A numeric matrix of \code{length(x)} rows and \code{df} columns if
\code{df} is specified. If \code{knots} are specified instead, the
output matrix will consist of \code{length(knots) + degree +
as.integer(intercept)} columns. Attributes that correspond to the
arguments specified are returned for usage of other functions in this
package.
}
\description{
Generates the I-spline (integral of M-spline) basis matrix for a polynomial
spline or the corresponding derivatives of given order.
}
\details{
It is an implementation of the closed-form I-spline basis based on the
recursion formula given by Ramsay (1988). The function \code{isp()} is an
alias of to encourage the use in a model formula.
}
\examples{
library(splines2)
## an example given in Ramsay (1988)
x <- seq.int(0, 1, by = 0.01)
knots <- c(0.3, 0.5, 0.6)
isMat <- iSpline(x, knots = knots, degree = 2)
op <- par(mar = c(2.5, 2.5, 0.2, 0.1), mgp = c(1.5, 0.5, 0))
plot(isMat, ylab = "I-spline basis", mark_knots = "internal")
par(op) # reset to previous plotting settings
## the derivative of I-splines is M-spline
msMat1 <- iSpline(x, knots = knots, degree = 2, derivs = 1)
msMat2 <- mSpline(x, knots = knots, degree = 2, intercept = TRUE)
stopifnot(all.equal(msMat1, msMat2))
}
\references{
Ramsay, J. O. (1988). Monotone regression splines in action.
\emph{Statistical Science}, 3(4), 425--441.
}
\seealso{
\code{\link{mSpline}} for M-splines;
\code{\link{cSpline}} for C-splines;
}
splines2/man/mSpline.Rd 0000644 0001762 0000144 00000016236 14441405225 014473 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/mSpline.R
\name{mSpline}
\alias{mSpline}
\alias{msp}
\title{M-Spline Basis for Polynomial Splines}
\usage{
mSpline(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = FALSE,
Boundary.knots = NULL,
periodic = FALSE,
derivs = 0L,
integral = FALSE,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
msp(
x,
df = NULL,
knots = NULL,
degree = 3L,
intercept = FALSE,
Boundary.knots = NULL,
periodic = FALSE,
derivs = 0L,
integral = FALSE,
warn.outside = getOption("splines2.warn.outside", TRUE),
...
)
}
\arguments{
\item{x}{The predictor variable. Missing values are allowed and will be
returned as they are.}
\item{df}{Degree of freedom that equals to the column number of the returned
matrix. One can specify \code{df} rather than \code{knots}, then the
function chooses \code{df - degree - as.integer(intercept)} internal
knots at suitable quantiles of \code{x} ignoring missing values and
those \code{x} outside of the boundary. For periodic splines, \code{df
- as.integer(intercept)} internal knots will be chosen at suitable
quantiles of \code{x} relative to the beginning of the cyclic intervals
they belong to (see Examples) and the number of internal knots must be
greater or equal to the specified \code{degree - 1}. If internal knots
are specified via \code{knots}, the specified \code{df} will be ignored.}
\item{knots}{The internal breakpoints that define the splines. The default
is \code{NULL}, which results in a basis for ordinary polynomial
regression. Typical values are the mean or median for one knot,
quantiles for more knots. For periodic splines, the number of knots
must be greater or equal to the specified \code{degree - 1}.}
\item{degree}{A nonnegative integer specifying the degree of the piecewise
polynomial. The default value is \code{3} for cubic splines. Zero degree
is allowed for piecewise constant basis functions.}
\item{intercept}{If \code{TRUE}, the complete basis matrix will be returned.
Otherwise, the first basis will be excluded from the output.}
\item{Boundary.knots}{Boundary points at which to anchor the splines. By
default, they are the range of \code{x} excluding \code{NA}. If both
\code{knots} and \code{Boundary.knots} are supplied, the basis
parameters do not depend on \code{x}. Data can extend beyond
\code{Boundary.knots}. For periodic splines, the specified bounary
knots define the cyclic interval.}
\item{periodic}{A logical value. If \code{TRUE}, the periodic splines will
be returned. The default value is \code{FALSE}.}
\item{derivs}{A nonnegative integer specifying the order of derivatives of
splines basis function. The default value is \code{0}.}
\item{integral}{A logical value. If \code{TRUE}, the corresponding
integrals of spline basis functions will be returned. The default value
is \code{FALSE}. For periodic splines, the integral of each basis is
integrated from the left boundary knot.}
\item{warn.outside}{A logical value indicating if a warning should be thrown
out when any \code{x} is outside the boundary. This option can also be
set through \code{options("splines2.warn.outside")} after the package is
loaded.}
\item{...}{Optional arguments that are not used.}
}
\value{
A numeric matrix of \code{length(x)} rows and \code{df} columns if
\code{df} is specified. If \code{knots} are specified instead, the
output matrix will consist of \code{length(knots) + degree +
as.integer(intercept)} columns if \code{periodic = FALSE}, or
\code{length(knots) + as.integer(intercept)} columns if \code{periodic =
TRUE}. Attributes that correspond to the arguments specified are
returned for usage of other functions in this package.
}
\description{
Generates the basis matrix of regular M-spline, periodic M-spline, and the
corresponding integrals and derivatives.
}
\details{
This function contains an implementation of the closed-form M-spline basis
based on the recursion formula given by Ramsay (1988) or periodic M-spline
basis following the procedure producing periodic B-splines given in Piegl
and Tiller (1997). For monotone regression, one can use I-splines (see
\code{\link{iSpline}}) instead of M-splines. For shape-restricted
regression, see Wang and Yan (2021) for examples.
The function \code{msp()} is an alias of to encourage the use in a model
formula.
}
\examples{
library(splines2)
### example given in the reference paper by Ramsay (1988)
x <- seq.int(0, 1, 0.01)
knots <- c(0.3, 0.5, 0.6)
msMat <- mSpline(x, knots = knots, degree = 2, intercept = TRUE)
op <- par(mar = c(2.5, 2.5, 0.2, 0.1), mgp = c(1.5, 0.5, 0))
plot(msMat, mark_knots = "internal")
## derivatives of M-splines
dmsMat <- mSpline(x, knots = knots, degree = 2,
intercept = TRUE, derivs = 1)
## or using the deriv method
dmsMat1 <- deriv(msMat)
stopifnot(all.equal(dmsMat, dmsMat1, check.attributes = FALSE))
### periodic M-splines
x <- seq.int(0, 3, 0.01)
bknots <- c(0, 1)
pMat <- mSpline(x, knots = knots, degree = 3, intercept = TRUE,
Boundary.knots = bknots, periodic = TRUE)
## integrals
iMat <- mSpline(x, knots = knots, degree = 3, intercept = TRUE,
Boundary.knots = bknots, periodic = TRUE, integral = TRUE)
## first derivatives by "derivs = 1"
dMat1 <- mSpline(x, knots = knots, degree = 3, intercept = TRUE,
Boundary.knots = bknots, periodic = TRUE, derivs = 1)
## first derivatives by using the deriv() method
dMat2 <- deriv(pMat)
par(mfrow = c(2, 2))
plot(pMat, ylab = "Periodic Basis", mark_knots = "boundary")
plot(iMat, ylab = "Integrals from 0")
abline(v = seq.int(0, max(x)), h = seq.int(0, max(x)), lty = 2, col = "grey")
plot(dMat1, ylab = "1st derivatives by 'derivs=1'", mark_knots = "boundary")
plot(dMat2, ylab = "1st derivatives by 'deriv()'", mark_knots = "boundary")
par(op) # reset to previous plotting settings
### default placement of internal knots for periodic splines
default_knots <- function(x, df, intercept = FALSE,
Boundary.knots = range(x, na.rm = TRUE)) {
## get x in the cyclic interval [0, 1)
x2 <- (x - Boundary.knots[1]) \%\% (Boundary.knots[2] - Boundary.knots[1])
knots <- quantile(x2, probs = seq(0, 1, length.out = df + 2 - intercept))
unname(knots[- c(1, length(knots))])
}
df <- 8
degree <- 3
intercept <- TRUE
internal_knots <- default_knots(x, df, intercept)
## 1. specify df
spline_basis1 = mSpline(x, degree = degree, df = df,
periodic = TRUE, intercept = intercept)
## 2. specify knots
spline_basis2 = mSpline(x, degree = degree, knots = internal_knots,
periodic = TRUE, intercept = intercept)
all.equal(internal_knots, knots(spline_basis1))
all.equal(spline_basis1, spline_basis2)
}
\references{
Ramsay, J. O. (1988). Monotone regression splines in action.
\emph{Statistical science}, 3(4), 425--441.
Piegl, L., & Tiller, W. (1997). \emph{The NURBS book}. Springer Science &
Business Media.
Wang, W., & Yan, J. (2021). \emph{Shape-restricted regression splines with R
package splines2}. Journal of Data Science, 19(3),498--517.
}
\seealso{
\code{\link{bSpline}} for B-splines;
\code{\link{iSpline}} for I-splines;
\code{\link{cSpline}} for C-splines.
}
splines2/DESCRIPTION 0000644 0001762 0000144 00000002661 14470217507 013533 0 ustar ligges users Package: splines2
Title: Regression Spline Functions and Classes
Version: 0.5.1
Authors@R: c(
person(given = "Wenjie", family = "Wang",
email = "wang@wwenjie.org",
role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-0363-3180")),
person(given = "Jun", family = "Yan", role = "aut",
comment = c(ORCID = "0000-0003-4401-7296"))
)
Description: Constructs basis functions of B-splines, M-splines,
I-splines, convex splines (C-splines), periodic splines,
natural cubic splines, generalized Bernstein polynomials,
their derivatives, and integrals (except C-splines)
by closed-form recursive formulas.
It also contains a C++ head-only library integrated with Rcpp.
See Wang and Yan (2021) for details.
Imports: stats, graphics, Rcpp
LinkingTo: Rcpp, RcppArmadillo
Suggests: knitr, rmarkdown, tinytest, RcppArmadillo
Depends: R (>= 3.2.3)
VignetteBuilder: knitr
License: GPL (>= 3)
URL: https://wwenjie.org/splines2,
https://github.com/wenjie2wang/splines2
BugReports: https://github.com/wenjie2wang/splines2/issues
Encoding: UTF-8
RoxygenNote: 7.2.3
NeedsCompilation: yes
Packaged: 2023-08-19 18:24:19 UTC; wenjie
Author: Wenjie Wang [aut, cre] (),
Jun Yan [aut] ()
Maintainer: Wenjie Wang
Repository: CRAN
Date/Publication: 2023-08-19 20:00:07 UTC
splines2/build/ 0000755 0001762 0000144 00000000000 14470204322 013106 5 ustar ligges users splines2/build/vignette.rds 0000644 0001762 0000144 00000000400 14470204322 015437 0 ustar ligges users uOQk0յk >@ѭWt4$E_;Eᄏ/
!dA