Rev 86303 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
% File src/library/stats/man/splinefun.Rd% Part of the R package, https://www.R-project.org% Copyright 1995-2025 R Core Team% Distributed under GPL 2 or later\name{splinefun}\alias{spline}\alias{splinefun}\alias{splinefunH}\title{Interpolating Splines}\description{Perform cubic (or Hermite) spline interpolation of given data points,returning either a list of points obtained by the interpolation or a\emph{function} performing the interpolation.}\usage{splinefun(x, y = NULL,method = c("fmm", "periodic", "natural", "monoH.FC", "hyman"),ties = mean)spline(x, y = NULL, n = 3*length(x), method = "fmm",xmin = min(x), xmax = max(x), xout, ties = mean)splinefunH(x, y, m)}\arguments{\item{x, y}{vectors giving the coordinates of the points to beinterpolated. Alternatively a single plotting structure can bespecified: see \code{\link{xy.coords}}.\code{y} must be increasing or decreasing for \code{method = "hyman"}.}\item{m}{(for \code{splinefunH()}): vector of \emph{slopes}\eqn{m_i}{m[i]} at the points \eqn{(x_i,y_i)}{(x[i],y[i])}; thesetogether determine the \bold{H}ermite \dQuote{spline} which ispiecewise cubic, (only) \emph{once} differentiable continuously.}\item{method}{specifies the type of spline to be used. Possiblevalues are \code{"fmm"}, \code{"natural"}, \code{"periodic"},\code{"monoH.FC"} and \code{"hyman"}. Can be abbreviated.}\item{n}{if \code{xout} is left unspecified, interpolation takes placeat \code{n} equally spaced points spanning the interval[\code{xmin}, \code{xmax}].}\item{xmin, xmax}{left-hand and right-hand endpoint of theinterpolation interval (when \code{xout} is unspecified).}\item{xout}{an optional set of values specifying where interpolationis to take place.}\item{ties}{handling of tied \code{x} values. The string\code{"ordered"} or a function (or the name of a function) taking asingle vector argument and returning a single number or a length-2\code{\link{list}} of both, see \code{\link{approx}} and its\sQuote{Details} section, and the example below.}}\details{The inputs can contain missing values which are deleted, so at leastone complete \code{(x, y)} pair is required.If \code{method = "fmm"}, the spline used is that of\bibcitet{R:Forsythe+Malcolm+Moler:1977}(an exact cubic is fitted through the four points at eachend of the data, and this is used to determine the end conditions).Natural splines are used when \code{method = "natural"}, and periodicsplines when \code{method = "periodic"}.The method \code{"monoH.FC"} computes a \emph{monotone} Hermite splineaccording to the method of \I{Fritsch} and \I{Carlson}. It does so bydetermining slopes such that the Hermite spline, determined by\eqn{(x_i,y_i,m_i)}{(x[i],y[i],m[i])}, is monotone (increasing ordecreasing) \bold{iff} the data are.Method \code{"hyman"} computes a \emph{monotone} cubic spline using\I{Hyman} filtering of an \code{method = "fmm"} fit for strictly monotonicinputs.These interpolation splines can also be used for extrapolation, that isprediction at points outside the range of \code{x}. Extrapolationmakes little sense for \code{method = "fmm"}; for natural splines itis linear using the slope of the interpolating curve at the nearestdata point.}\value{\code{spline} returns a list containing components \code{x} and\code{y} which give the ordinates where interpolation took place andthe interpolated values.\code{splinefun} returns a function with formal arguments \code{x} and\code{deriv}, the latter defaulting to zero. This functioncan be used to evaluate the interpolating cubic spline(\code{deriv} = 0), or its derivatives (\code{deriv} = 1, 2, 3) at thepoints \code{x}, where the spline function interpolates the datapoints originally specified. It uses data stored in its environmentwhen it was created, the details of which are subject to change.}\section{Warning}{The value returned by \code{splinefun} contains references to the codein the current version of \R: it is not intended to be saved andloaded into a different \R session. This is safer in \R >= 3.0.0.}\references{\bibshow{*,R:Becker+Chambers+Wilks:1988,R:Dougherty+Edelman+Hyman:1989,R:Fritsch+Carlson:1980,R:Hyman:1983}}\seealso{\code{\link{approx}} and \code{\link{approxfun}} for constant andlinear interpolation.Package \pkg{splines}, especially \code{\link[splines]{interpSpline}}and \code{\link[splines]{periodicSpline}} for interpolation splines.That package also generates spline bases that can be used forregression splines.\code{\link{smooth.spline}} for smoothing splines.}\author{R Core Team.Simon Wood for the original code for Hyman filtering.}\examples{require(graphics)op <- par(mfrow = c(2,1), mgp = c(2,.8,0), mar = 0.1+c(3,3,3,1))n <- 9x <- 1:ny <- rnorm(n)plot(x, y, main = paste("spline[fun](.) through", n, "points"))lines(spline(x, y))lines(spline(x, y, n = 201), col = 2)y <- (x-6)^2plot(x, y, main = "spline(.) -- 3 methods")lines(spline(x, y, n = 201), col = 2)lines(spline(x, y, n = 201, method = "natural"), col = 3)lines(spline(x, y, n = 201, method = "periodic"), col = 4)legend(6, 25, c("fmm","natural","periodic"), col = 2:4, lty = 1)y <- sin((x-0.5)*pi)f <- splinefun(x, y)ls(envir = environment(f))splinecoef <- get("z", envir = environment(f))curve(f(x), 1, 10, col = "green", lwd = 1.5)points(splinecoef, col = "purple", cex = 2)curve(f(x, deriv = 1), 1, 10, col = 2, lwd = 1.5)curve(f(x, deriv = 2), 1, 10, col = 2, lwd = 1.5, n = 401)curve(f(x, deriv = 3), 1, 10, col = 2, lwd = 1.5, n = 401)par(op)## Manual spline evaluation --- demo the coefficients :.x <- splinecoef$xu <- seq(3, 6, by = 0.25)(ii <- findInterval(u, .x))dx <- u - .x[ii]f.u <- with(splinecoef,y[ii] + dx*(b[ii] + dx*(c[ii] + dx* d[ii])))stopifnot(all.equal(f(u), f.u))## An example with ties (non-unique x values):set.seed(1); x <- round(rnorm(30), 1); y <- sin(pi * x) + rnorm(30)/10plot(x, y, main = "spline(x,y) when x has ties")lines(spline(x, y, n = 201), col = 2)## visualizes the non-unique ones:tx <- table(x); mx <- as.numeric(names(tx[tx > 1]))ry <- matrix(unlist(tapply(y, match(x, mx), range, simplify = FALSE)),ncol = 2, byrow = TRUE)segments(mx, ry[, 1], mx, ry[, 2], col = "blue", lwd = 2)## Another example with sorted x, but ties:set.seed(8); x <- sort(round(rnorm(30), 1)); y <- round(sin(pi * x) + rnorm(30)/10, 3)summary(diff(x) == 0) # -> 7 duplicated x-valuesstr(spline(x, y, n = 201, ties="ordered")) # all '$y' entries are NaN## The default (ties=mean) is ok, but most efficient to use instead issxyo <- spline(x, y, n = 201, ties= list("ordered", mean))sapply(sxyo, summary)# all fine nowplot(x, y, main = "spline(x,y, ties=list(\"ordered\", mean)) for when x has ties")lines(sxyo, col="blue")## An example of monotone interpolationn <- 20set.seed(11)x. <- sort(runif(n)) ; y. <- cumsum(abs(rnorm(n)))plot(x., y.)curve(splinefun(x., y.)(x), add = TRUE, col = 2, n = 1001)curve(splinefun(x., y., method = "monoH.FC")(x), add = TRUE, col = 3, n = 1001)curve(splinefun(x., y., method = "hyman") (x), add = TRUE, col = 4, n = 1001)legend("topleft",paste0("splinefun( \"", c("fmm", "monoH.FC", "hyman"), "\" )"),col = 2:4, lty = 1, bty = "n")## and one from Fritsch and Carlson (1980), Dougherty et al (1989)x. <- c(7.09, 8.09, 8.19, 8.7, 9.2, 10, 12, 15, 20)f <- c(0, 2.76429e-5, 4.37498e-2, 0.169183, 0.469428, 0.943740,0.998636, 0.999919, 0.999994)s0 <- splinefun(x., f)s1 <- splinefun(x., f, method = "monoH.FC")s2 <- splinefun(x., f, method = "hyman")plot(x., f, ylim = c(-0.2, 1.2))curve(s0(x), add = TRUE, col = 2, n = 1001) -> m0curve(s1(x), add = TRUE, col = 3, n = 1001)curve(s2(x), add = TRUE, col = 4, n = 1001)legend("right",paste0("splinefun( \"", c("fmm", "monoH.FC", "hyman"), "\" )"),col = 2:4, lty = 1, bty = "n")## they seem identical, but are not quite:xx <- m0$xplot(xx, s1(xx) - s2(xx), type = "l", col = 2, lwd = 2,main = "Difference monoH.FC - hyman"); abline(h = 0, lty = 3)x <- xx[xx < 10.2] ## full range: x <- xx .. does not show enoughccol <- adjustcolor(2:4, 0.8)matplot(x, cbind(s0(x, deriv = 2), s1(x, deriv = 2), s2(x, deriv = 2))^2,lwd = 2, col = ccol, type = "l", ylab = quote({{f*second}(x)}^2),main = expression({{f*second}(x)}^2 ~" for the three 'splines'"))legend("topright",paste0("splinefun( \"", c("fmm", "monoH.FC", "hyman"), "\" )"),lwd = 2, col = ccol, lty = 1:3, bty = "n")## --> "hyman" has slightly smaller Integral f''(x)^2 dx than "FC",## here, and both are 'much worse' than the regular fmm spline.}\keyword{math}\keyword{dplot}