Package {prinsurf}


Type: Package
Title: Principal Surface Contour Biplots
Version: 2.0
Description: Fits principal surfaces, the two-dimensional generalisation of the principal curves of Hastie and Stuetzle (1989) <doi:10.1080/01621459.1989.10478797>, and displays them as biplots in which each variable is read off the contour lines of its fitted surface coordinate function. Sample predictivity, the proportion of a sample's squared length that is reconstructed by the fitted surface, is reported as a per-sample diagnostic of how well the surface represents the data.
License: MIT + file LICENSE
URL: https://raeesaganey91.github.io/prinsurf/, https://github.com/RaeesaGaney91/prinsurf
BugReports: https://github.com/RaeesaGaney91/prinsurf/issues
Encoding: UTF-8
Depends: R (≥ 4.1.0)
Imports: stats, graphics, grDevices
Suggests: testthat (≥ 3.0.0), knitr, rmarkdown, biplotEZ
VignetteBuilder: knitr
NeedsCompilation: no
Packaged: 2026-09-09 11:54:31 UTC; raeesaganey
Author: Raeesa Ganey [aut, cre, cph]
Maintainer: Raeesa Ganey <raeesa.ganey@wits.ac.za>
Config/roxygen2/version: 8.0.0
Repository: CRAN
Date/Publication: 2026-09-09 12:20:02 UTC

Contour reading error

Description

For each variable, the root-mean-square difference between the value read from the variable's contour lines at each sample's biplot position (as predict.prinsurf does) and the sample's actual value. This measures how accurately a variable can be recovered by reading its contours, combining the surface's lack of fit for that variable with the small loss from interpolating between contour lines; lower is better, in the units of the working data. Samples that fall outside the supported part of the contour grid cannot be read and are excluded; their number is returned as the attribute "n.unread".

Usage

contour_predictive_error(object)

Arguments

object

A "prinsurf" object.

Value

A named numeric vector of per-variable RMS contour-reading errors, with the mean over all variables as the attribute "overall" and the number of unreadable samples as the attribute "n.unread".

See Also

predictivity for whole-sample reconstruction.


Fitted (reconstructed) values from a principal surface

Description

Returns the fitted surface values \hat f_j(\lambda_i) for every sample and variable: the point on the surface at which sample i sits, written back in the coordinates of the original variables. Row i is the surface's reconstruction of sample i – what the fit says the sample would be if it lay exactly on the surface – and the residual x_i - \hat f(\lambda_i) is the part of the sample the surface does not capture, which is what predictivity summarises.

Usage

## S3 method for class 'prinsurf'
fitted(object, ...)

Arguments

object

A "prinsurf" object.

...

Ignored.

Details

Values are in the working units used for fitting: centred, and divided by each variable's standard deviation if the surface was fitted with scale = TRUE. This is the scale on which residuals and predictivity are computed. predict.prinsurf differs in two ways: it reads values off the plotted contour grid rather than evaluating the coordinate functions exactly, and it returns them on the variables' original scales.

Value

An n \times p matrix of fitted values, in working (centred, optionally scaled) units.

See Also

predictivity for the per-sample quality of this reconstruction, and predict.prinsurf for the values a reader obtains from the contours.


Plot a principal-surface biplot

Description

Draws the sample coordinates. If vars is given, draws one panel per named variable, each showing the sample coordinates together with that variable's contour lines - the surface's analogue of a biplot axis, read by interpolating between contour lines rather than by projection onto a single calibrated axis. With no vars, a single panel of sample coordinates is drawn with no contours.

Usage

## S3 method for class 'prinsurf'
plot(
  x,
  vars = NULL,
  group = NULL,
  col_contour = "grey40",
  nlevels = 6,
  pch = 16,
  cex = 0.7,
  asp = 1,
  main = NULL,
  outer_main = NULL,
  ...
)

Arguments

x

A "prinsurf" object.

vars

Variables to contour, one panel each (default: none – a bare scatter of sample coordinates).

group

Optional factor to colour the sample points.

col_contour

Colour for the contour lines.

nlevels

Number of contour levels per panel.

pch, cex

Point symbol and size for samples.

asp

Aspect ratio of each panel; the default 1 keeps the two surface coordinates on a common scale, so distances in the biplot are comparable in every direction.

main

Panel title(s), replacing the default (the variable's name, or no title when vars is not given). A single string titles every panel; a vector titles the panels in the order of vars and is recycled to that length. Use "" for no panel titles.

outer_main

A single title for the figure as a whole, drawn in the outer margin above the panels. Can be combined with main, which titles the individual panels.

...

Passed to each panel's initial plot.

Value

Invisibly, vars.

Examples

set.seed(1)
s <- runif(120, -1, 1); t <- runif(120, -1, 1)
X <- cbind(x = s, y = t, z = 0.7 * s + 0.9 * t^2) +
     matrix(rnorm(360, 0, 0.03), 120, 3)
fit <- prinsurf(X, max.iter = 6)

## default: each panel is titled with its variable's name
plot(fit, vars = c("x", "z"))

## your own panel titles, and a title for the figure as a whole
plot(fit, vars = c("x", "z"),
     main = c("First coordinate", "Third coordinate"),
     outer_main = "Principal-surface biplot")

## a title on a single, contour-free panel
plot(fit, main = "Sample coordinates")

Predict all variables from the biplot contours

Description

Reads every variable's value for every sample off that variable's contour lines at the sample's biplot position \lambda_i – the same interpolation used to draw the contours in plot.prinsurf. Values come from the contour grid alone: a sample whose position is not covered by the supported part of the grid has no contours to read, and is returned as NA for every variable.

Usage

## S3 method for class 'prinsurf'
predict(object, ...)

Arguments

object

A "prinsurf" object.

...

Ignored.

Value

An n \times p matrix of values read from the contours, on the variables' original scales, with NA rows where the biplot cannot be read.

See Also

contour_predictive_error to measure this reading against the variables' actual values, and fitted.prinsurf for the surface's own reconstruction of the data.


Sample predictivity of a principal-surface biplot

Description

For each sample, the proportion of its squared length reconstructed by the fitted surface, 1 - \lVert x_i - \hat f(\lambda_i) \rVert^2 / \lVert x_i \rVert^2. This is the principal-surface analogue of biplot sample predictivity and is read from the sample's position on the surface.

Usage

predictivity(object)

Arguments

object

A "prinsurf" object.

Value

A numeric vector of per-sample predictivities (with the overall mean as the attribute "overall").


Fit a principal surface

Description

Fits a two-dimensional principal surface to a numeric data matrix using the iterative expectation / projection algorithm of Hastie and Stuetzle (1989), with the coordinate functions estimated by local regression (loess).

Usage

prinsurf(X, max.iter = 10, span = 0.6, scale = FALSE, verbose = FALSE)

Arguments

X

A numeric matrix or data frame, n \times p. Column names are used as variable names; if absent, V1, V2, ... are assigned.

max.iter

Maximum number of expectation/projection iterations.

span

The loess span (\alpha) used for the coordinate functions.

scale

Logical; if TRUE each variable is standardised to unit standard deviation before fitting (recommended when variables are on very different scales). Variables are always centred.

verbose

Logical; print the relative change and residual sum of squares at each iteration.

Value

An object of class "prinsurf": a list with elements lambda (the n \times 2 surface coordinates of the samples), fj.mat (the fitted surface coordinates of the samples in the working units), models (the per-variable loess coordinate functions), varnames, center, scale, span and iterations.

References

Hastie, T. and Stuetzle, W. (1989) Principal curves. Journal of the American Statistical Association 84, 502–516.

Examples

set.seed(1)
s <- runif(120, -1, 1); t <- runif(120, -1, 1)
X <- cbind(x = s, y = t, z = 0.7 * s + 0.9 * t^2) +
     matrix(rnorm(360, 0, 0.03), 120, 3)
fit <- prinsurf(X, max.iter = 6)
fit