| Title: | S3 Classes and Methods for Tidy Functional Data |
|---|---|
| Description: | Provides S3 vector types for functional data represented on grids, in spline bases, or via functional principal components. Supports arithmetic and summary methods, plotting, derivation, integration, smoothing, registration, and data import/export for these functional vectors. Includes data-wrangling tools for re-evaluation, subsetting, sub-assignment, zooming into sub-domains, and extracting functional features such as minima, maxima, and their locations. Enables joint analysis of functional and scalar variables by integrating functional vectors into standard data frames. |
| Authors: | Fabian Scheipl [aut, cre, cph] (ORCID: <https://orcid.org/0000-0001-8172-3603>), Jeff Goldsmith [aut], Maximilian Mücke [aut] (ORCID: <https://orcid.org/0009-0000-9432-9795>), Julia Wrobel [ctb] (ORCID: <https://orcid.org/0000-0001-6783-1421>), Sebastian Fischer [ctb] (ORCID: <https://orcid.org/0000-0002-9609-3197>) |
| Maintainer: | Fabian Scheipl <[email protected]> |
| License: | AGPL (>= 3) |
| Version: | 0.5.0.9000 |
| Built: | 2026-07-15 17:05:08 UTC |
| Source: | https://github.com/tidyfun/tf |
tf vectorsThese functions access, subset, replace and evaluate tf objects.
For more information on creating tf objects and converting them to/from
list, data.frame or matrix, see tfd() and tfb(). See details.
## S3 method for class 'tf_mv' x[i, j, component = NULL, interpolate = TRUE, matrix = TRUE] ## S3 replacement method for class 'tf_mv' x[i] <- value ## S3 method for class 'tf' x[i, j, interpolate = TRUE, matrix = TRUE] ## S3 replacement method for class 'tf' x[i] <- value## S3 method for class 'tf_mv' x[i, j, component = NULL, interpolate = TRUE, matrix = TRUE] ## S3 replacement method for class 'tf_mv' x[i] <- value ## S3 method for class 'tf' x[i, j, interpolate = TRUE, matrix = TRUE] ## S3 replacement method for class 'tf' x[i] <- value
x |
an |
i |
index of the observations ( |
j |
The |
component |
for |
interpolate |
should functions be evaluated (i.e., inter-/extrapolated)
for values in |
matrix |
should the result be returned as a |
value |
|
Note that these break certain (terrible) R conventions for vector-like objects:
no argument recycling,
no indexing with NA,
no indexing with names not present in x,
no indexing with integers > length(x)
All of the above will trigger errors.
If i is a two-column matrix, a numeric vector of pointwise
evaluations (one per row of i).
If j is missing (and i is not a matrix), a subset of the functions in
x as given by i.
If j is given and matrix == TRUE, a numeric
matrix of function evaluations in which each row represents one function
and each column represents one argval as given in argument j, with an
attribute arg=j and row- and column-names derived from x[i] and
j.
If j is given and matrix == FALSE, a list of tbl_dfs with
columns arg = j and value = evaluations at j for each observation
in i.
x <- 1:3 * tfd(data = 0:10, arg = 0:10) plot(x) # this operator's 2nd argument is quite overloaded -- you can: # 1. simply extract elements from the vector if no second arg is given: x[1] x[c(TRUE, FALSE, FALSE)] x[-(2:3)] # 2. use the second argument and optional additional arguments to # extract specific function evaluations in a number of formats: x[1:2, c(4.5, 9)] # returns a matrix of function evaluations x[1:2, c(4.5, 9), interpolate = FALSE] # NA for arg-values not in the original data x[-3, seq(1, 9, by = 2), matrix = FALSE] # list of data.frames for each function # 3. use a 2-column matrix to extract specific (function, arg) pairs: x[cbind(1:3, c(0, 5, 10))] # one value per function # 4. use matrix= with a missing j to evaluate on the default arg grid: x[1:2, , matrix = FALSE] # same as x[1:2, tf_arg(x), matrix = FALSE] # in order to evaluate a set of observed functions on a new grid and # save them as a functional data vector again, use `tfd` or `tfb` instead: tfd(x, arg = seq(0, 10, by = 0.01))x <- 1:3 * tfd(data = 0:10, arg = 0:10) plot(x) # this operator's 2nd argument is quite overloaded -- you can: # 1. simply extract elements from the vector if no second arg is given: x[1] x[c(TRUE, FALSE, FALSE)] x[-(2:3)] # 2. use the second argument and optional additional arguments to # extract specific function evaluations in a number of formats: x[1:2, c(4.5, 9)] # returns a matrix of function evaluations x[1:2, c(4.5, 9), interpolate = FALSE] # NA for arg-values not in the original data x[-3, seq(1, 9, by = 2), matrix = FALSE] # list of data.frames for each function # 3. use a 2-column matrix to extract specific (function, arg) pairs: x[cbind(1:3, c(0, 5, 10))] # one value per function # 4. use matrix= with a missing j to evaluate on the default arg grid: x[1:2, , matrix = FALSE] # same as x[1:2, tf_arg(x), matrix = FALSE] # in order to evaluate a set of observed functions on a new grid and # save them as a functional data vector again, use `tfd` or `tfb` instead: tfd(x, arg = seq(0, 10, by = 0.01))
Various converters to turn tfb- or tfd-vectors into data.frames or
matrices, or even an actual R function.
## S3 method for class 'tf' as.data.frame(x, row.names = NULL, optional = FALSE, unnest = FALSE, ...) ## S3 method for class 'tf' as.matrix(x, arg, interpolate = FALSE, ...) ## S3 method for class 'tf' as.function(x, ...)## S3 method for class 'tf' as.data.frame(x, row.names = NULL, optional = FALSE, unnest = FALSE, ...) ## S3 method for class 'tf' as.matrix(x, arg, interpolate = FALSE, ...) ## S3 method for class 'tf' as.function(x, ...)
x |
a |
row.names |
|
optional |
not used. |
unnest |
if |
... |
additional arguments to be passed to or from methods. |
arg |
a vector of argument values / evaluation points for |
interpolate |
should functions be evaluated (i.e., inter-/extrapolated)
for values in |
for as.data.frame.tf: if unnest is FALSE (default), a
one-column data.frame with a tf-column containing x. if unnest is
TRUE, a 3-column data frame with columns id (containing (unique) names of
x or a numeric identifier if x is unnamed), arg, and value, with each row containing
one function evaluation at the original arg-values.
for as.matrix.tf: a matrix with one row per function and one
column per arg.
for as.function.tf: an R function with argument arg that
evaluates x on arg and returns the list of function values
Other tidyfun converters:
converters-mv
f <- tfd(sin(seq(0, 2 * pi, length.out = 11)), arg = seq(0, 1, length.out = 11)) as.data.frame(f) as.data.frame(f, unnest = TRUE) as.matrix(f) fun <- as.function(f) fun(c(0, 0.5, 1))f <- tfd(sin(seq(0, 2 * pi, length.out = 11)), arg = seq(0, 1, length.out = 11)) as.data.frame(f) as.data.frame(f, unnest = TRUE) as.matrix(f) fun <- as.function(f) fun(c(0, 0.5, 1))
tf_mv to a matrix or data.frameas.matrix.tf_mv returns a 3-d array [curve, arg, component] – the
natural shape for a vector-valued evaluation. This is deliberately
different from as.matrix.tf (2-d, [curve, arg]); see @seealso.
## S3 method for class 'tf_mv' as.matrix(x, arg, interpolate = FALSE, ...) ## S3 method for class 'tf_mv' as.data.frame( x, row.names = NULL, optional = FALSE, unnest = FALSE, long = TRUE, arg = NULL, interpolate = TRUE, grids = c("union", "component"), ... )## S3 method for class 'tf_mv' as.matrix(x, arg, interpolate = FALSE, ...) ## S3 method for class 'tf_mv' as.data.frame( x, row.names = NULL, optional = FALSE, unnest = FALSE, long = TRUE, arg = NULL, interpolate = TRUE, grids = c("union", "component"), ... )
x |
a |
arg |
optional evaluation grid (numeric vector or per-curve list).
When |
interpolate |
forwarded to the underlying |
... |
passed through. |
row.names, optional
|
standard |
unnest |
if |
long |
when |
grids |
when |
as.data.frame.tf_mv returns either a single-column wrapping data.frame
(unnest = FALSE, for storing a tf_mv in a tibble column) or an
evaluated long/wide data.frame (unnest = TRUE).
a 3-d array (as.matrix.tf_mv) or a data.frame (as.data.frame.tf_mv).
as.matrix.tf() (2-d sibling), as.data.frame.tf() (univariate
contract), tf_evaluate().
Other tidyfun converters:
as.data.frame.tf()
arg <- seq(0, 1, length.out = 11) xf <- tfd(t(sapply(1:3, function(i) sin(2 * pi * arg + i))), arg = arg) yf <- tfd(t(sapply(1:3, function(i) cos(2 * pi * arg + i))), arg = arg) mv <- tfd_mv(list(x = xf, y = yf)) dim(as.matrix(mv)) head(as.data.frame(mv, unnest = TRUE))arg <- seq(0, 1, length.out = 11) xf <- tfd(t(sapply(1:3, function(i) sin(2 * pi * arg + i))), arg = arg) yf <- tfd(t(sapply(1:3, function(i) cos(2 * pi * arg + i))), arg = arg) mv <- tfd_mv(list(x = xf, y = yf)) dim(as.matrix(mv)) head(as.data.frame(mv, unnest = TRUE))
Returns x unchanged if it is already a list, otherwise wraps it in
a one-element list. Used internally to normalize arg inputs that may
be either a single numeric vector or a list of per-curve vectors.
ensure_list(x)ensure_list(x)
x |
any input. |
x if it is a list, otherwise list(x).
Other tidyfun utility functions:
in_range(),
tf_arg(),
tf_zoom(),
unique_id()
ensure_list(1:3) ensure_list(list(1:3, 4:6))ensure_list(1:3) ensure_list(list(1:3, 4:6))
tf vectorsComputes a depth-based five number summary for functional data: the observations with minimum, lower-hinge, median, upper-hinge, and maximum depth values.
fivenum(x, na.rm = FALSE, ...) ## Default S3 method: fivenum(x, na.rm = FALSE, ...) ## S3 method for class 'tf' fivenum(x, na.rm = FALSE, depth = "MHI", ...) ## S3 method for class 'tf_mv' fivenum(x, na.rm = FALSE, depth = "MBD", ...)fivenum(x, na.rm = FALSE, ...) ## Default S3 method: fivenum(x, na.rm = FALSE, ...) ## S3 method for class 'tf' fivenum(x, na.rm = FALSE, depth = "MHI", ...) ## S3 method for class 'tf_mv' fivenum(x, na.rm = FALSE, depth = "MBD", ...)
x |
a |
na.rm |
logical; if |
... |
passed to |
depth |
depth method for ordering. See |
fivenum.tf: a named tf vector of length 5.fivenum.default: see stats::fivenum().
Other tidyfun summary functions:
functionwise,
median.tf_mv(),
tfsummaries
set.seed(1) f <- tf_rgp(7) fivenum(f)set.seed(1) f <- tf_rgp(7) fivenum(f)
Compute (truncated) orthonormal eigenfunctions and scores for (partially missing) data on a common (potentially non-equidistant) grid.
fpc_wsvd(data, arg, pve = 0.995) ## S3 method for class 'matrix' fpc_wsvd(data, arg, pve = 0.995) ## S3 method for class 'data.frame' fpc_wsvd(data, arg, pve = 0.995)fpc_wsvd(data, arg, pve = 0.995) ## S3 method for class 'matrix' fpc_wsvd(data, arg, pve = 0.995) ## S3 method for class 'data.frame' fpc_wsvd(data, arg, pve = 0.995)
data |
numeric matrix of function evaluations (each row is one curve, no NAs). |
arg |
numeric vector of argument values. |
pve |
percentage of variance explained. |
Performs a weighted SVD with trapezoidal quadrature weights s.t. returned
vectors represent (evaluations of)
orthonormal eigenfunctions , not eigenvectors
, specifically:
given quadrature weights , not
; not
.
For incomplete data, this uses a soft-impute iterative-SVD scheme
(see references). Note that this will not work well for data on a common grid
if more than a few percent of data points are missing, and it breaks down
completely for truly irregular data with no/few common timepoints, even if
observed very densely. For such data, either re-evaluate on a common grid
first or use more advanced FPCA approaches like refund::fpca_sc(),
see last example for tfb_fpc()
a list with entries
mu estimated mean function (numeric vector)
efunctions estimated FPCs (numeric matrix, columns represent FPCs)
scores estimated FPC scores (one row per observed curve)
npc how many FPCs were returned for the given pve (integer)
scoring_function a function that returns FPC scores for new data
and given eigenfunctions, see tf:::.fpc_wsvd_scores for an example.
Fabian Scheipl
the soft-impute SVD algorithm for incomplete data is described in Mazumder, Rahul, Hastie, Trevor, Tibshirani, Robert (2010). “Spectral Regularization Algorithms for Learning Large Incomplete Matrices.” The Journal of Machine Learning Research, 11, 2287–2322.
Other tfb-class:
tfb(),
tfb_fpc(),
tfb_spline()
Other tfb_fpc-class:
tfb_fpc(),
tfb_mfpc()
arg <- seq(0, 1, length.out = 41) data <- t(sapply(seq(0, 2 * pi, length.out = 10), function(p) sin(2 * pi * arg + p))) fpc <- fpc_wsvd(data, arg = arg, pve = 0.99) fpc$npcarg <- seq(0, 1, length.out = 41) data <- t(sapply(seq(0, 2 * pi, length.out = 10), function(p) sin(2 * pi * arg + p))) fpc <- fpc_wsvd(data, arg = arg, pve = 0.99) fpc$npc
tf in a vector (function-wise)These functions extract (user-specified) function-wise summary statistics
from every entry in a tf-vector. To summarize a vector of functions at each
argument value, see ?tfsummaries. Note that most of these will tend to yield lots
of NAs for irregular tfd unless you set a tf_evaluator()-function
that does inter- and extrapolation for them beforehand.
tf_fwise(x, .f, arg = tf_arg(x), ...) tf_fmax(x, arg = tf_arg(x), na.rm = FALSE) ## S3 method for class 'tf_mv' tf_fmax(x, arg = tf_arg(x), na.rm = FALSE) tf_fmin(x, arg = tf_arg(x), na.rm = FALSE) ## S3 method for class 'tf_mv' tf_fmin(x, arg = tf_arg(x), na.rm = FALSE) tf_fmedian(x, arg = tf_arg(x), na.rm = FALSE) ## S3 method for class 'tf_mv' tf_fmedian(x, arg = tf_arg(x), na.rm = FALSE) tf_frange(x, arg = tf_arg(x), na.rm = FALSE, finite = FALSE) tf_fmean(x, arg = tf_arg(x)) ## S3 method for class 'tf_mv' tf_fmean(x, arg = tf_arg(x)) tf_fvar(x, arg = tf_arg(x)) ## S3 method for class 'tf_mv' tf_fvar(x, arg = tf_arg(x)) tf_fsd(x, arg = tf_arg(x)) ## S3 method for class 'tf_mv' tf_fsd(x, arg = tf_arg(x)) tf_crosscov(x, y, arg = tf_arg(x)) tf_crosscor(x, y, arg = tf_arg(x))tf_fwise(x, .f, arg = tf_arg(x), ...) tf_fmax(x, arg = tf_arg(x), na.rm = FALSE) ## S3 method for class 'tf_mv' tf_fmax(x, arg = tf_arg(x), na.rm = FALSE) tf_fmin(x, arg = tf_arg(x), na.rm = FALSE) ## S3 method for class 'tf_mv' tf_fmin(x, arg = tf_arg(x), na.rm = FALSE) tf_fmedian(x, arg = tf_arg(x), na.rm = FALSE) ## S3 method for class 'tf_mv' tf_fmedian(x, arg = tf_arg(x), na.rm = FALSE) tf_frange(x, arg = tf_arg(x), na.rm = FALSE, finite = FALSE) tf_fmean(x, arg = tf_arg(x)) ## S3 method for class 'tf_mv' tf_fmean(x, arg = tf_arg(x)) tf_fvar(x, arg = tf_arg(x)) ## S3 method for class 'tf_mv' tf_fvar(x, arg = tf_arg(x)) tf_fsd(x, arg = tf_arg(x)) ## S3 method for class 'tf_mv' tf_fsd(x, arg = tf_arg(x)) tf_crosscov(x, y, arg = tf_arg(x)) tf_crosscor(x, y, arg = tf_arg(x))
x |
a |
.f |
a function or formula that is applied to each entry of |
arg |
defaults to standard argument values of |
... |
additional arguments for |
na.rm |
a logical ( |
finite |
logical, indicating if all non-finite elements should be omitted. |
y |
a |
tf_fwise turns x into a list of data.frames with columns arg
and values internally, so the function/formula in .f gets a data.frame
.x with these columns, see examples below or source code for tf_fmin(),
tf_fmax(), etc.
a list (or vector) of the same length as x with the respective
summaries.
tf_fwise(): User-specified function-wise summary statistics
tf_fmax(): maximal value of each function
tf_fmax(tf_mv): component-wise maxima of each vector-valued function
tf_fmin(): minimal value of each function
tf_fmin(tf_mv): component-wise minima of each vector-valued function
tf_fmedian(): median value of each function
tf_fmedian(tf_mv): component-wise medians of each vector-valued function
tf_frange(): range of values of each function
tf_fmean(): mean of each function:
tf_fmean(tf_mv): component-wise means of each vector-valued function
tf_fvar(): variance of each function:
tf_fvar(tf_mv): component-wise variances of each vector-valued function
tf_fsd(): standard deviation of each function:
tf_fsd(tf_mv): component-wise standard deviations of each vector-valued function
tf_crosscov(): cross-covariances between two functional vectors:
tf_crosscor(): cross-correlation between two functional vectors:
tf_crosscov(x, y) / (tf_fsd(x) * tf_fsd(y))
Other tidyfun summary functions:
fivenum(),
median.tf_mv(),
tfsummaries
x <- tf_rgp(3) layout(t(1:3)) plot(x, col = 1:3) # each function's values to [0,1]: x_clamp <- (x - tf_fmin(x)) / (tf_fmax(x) - tf_fmin(x)) plot(x_clamp, col = 1:3) # standardize each function to have mean / integral 0 and sd 1: x_std <- (x - tf_fmean(x)) / tf_fsd(x) tf_fvar(x_std) == c(1, 1, 1) plot(x_std, col = 1:3) # Custom functions: # 80%tiles of each function's values: tf_fwise(x, \(.x) quantile(.x$value, 0.8)) |> unlist() # minimal value of each function for t > 0.5 tf_fwise(x, \(.x) min(.x$value[.x$arg > 0.5])) |> unlist() tf_crosscor(x, -x) tf_crosscov(x, x) == tf_fvar(x)x <- tf_rgp(3) layout(t(1:3)) plot(x, col = 1:3) # each function's values to [0,1]: x_clamp <- (x - tf_fmin(x)) / (tf_fmax(x) - tf_fmin(x)) plot(x_clamp, col = 1:3) # standardize each function to have mean / integral 0 and sd 1: x_std <- (x - tf_fmean(x)) / tf_fsd(x) tf_fvar(x_std) == c(1, 1, 1) plot(x_std, col = 1:3) # Custom functions: # 80%tiles of each function's values: tf_fwise(x, \(.x) quantile(.x$value, 0.8)) |> unlist() # minimal value of each function for t > 0.5 tf_fwise(x, \(.x) min(.x$value[.x$arg > 0.5])) |> unlist() tf_crosscor(x, -x) tf_crosscov(x, x) == tf_fvar(x)
Hip and knee angle measurements in degrees through a 20-point movement cycle for 39 children. The data represents the angular positions of hip and knee joints during normal walking gait, captured at evenly spaced time points throughout the gait cycle.
gaitgait
A data frame with 39 rows and 3 variables:
subject identifier
a tfd column of knee-joint angles (degrees)
a tfd column of hip-joint angles (degrees)
Data is also included in the fda package in another format.
Olshen, A R, Biden, N E, Wyatt, P M, Sutherland, H D (1989). “Gait Analysis and the Bootstrap.” The Annals of Statistics, 17(4), 1419–1440.
head(gait)head(gait)
Heights of 39 boys and 54 girls measured from age 1 to 18 years as part of the Berkeley Growth Study. The data tracks physical development over time with measurements at 31 different ages that are not equally spaced.
growthgrowth
A data frame with 93 rows and 2 variables:
sex of the subject, a factor with levels female/male
a tfd column of height-over-age curves (cm)
Data is also included in the fda package in another format.
Ramsay, O. J, Hooker, Giles, Graves, Spencer (2009). Functional Data Analysis with R and MATLAB, series Use R!, 1 edition. Springer New York, New York. ISBN 978-0-387-98184-0. doi:10.1007/978-0-387-98185-7.
Ramsay, O. J, Silverman, W. B (2005). Functional Data Analysis, series Springer Series in Statistics, 2nd edition. Springer, New York. ISBN 978-0-387-40080-8.
Ramsay, O. J, Silverman, W. B (2002). Applied Functional Data Analysis. Springer.
Tuddenham, D R (1954). “Physical growth of California boys and girls from birth to eighteen years.” University of California Publications in Child Development, 1, 183–364.
head(growth)head(growth)
in_range and its infix-equivalent %inr% return TRUE for all values in
the numeric vector f that are within the range of values in r.
in_range(f, r) f %inr% rin_range(f, r) f %inr% r
f |
a numeric vector. |
r |
numeric vector used to specify a range, only the minimum and maximum
of |
a logical vector of the same length as f.
Other tidyfun utility functions:
ensure_list(),
tf_arg(),
tf_zoom(),
unique_id()
in_range(1:10, c(3, 7)) 1:10 %inr% c(3, 7)in_range(1:10, c(3, 7)) 1:10 %inr% c(3, 7)
The median of a tf_mv vector is the single observed curve with maximal
joint depth (see tf_depth()): one which.max index selects the same
observation across every component, so the result is never a "chimera"
stitched together from different curves. Note the deliberate divergence from
median.tf() on ties: the univariate median averages tied maximal-depth
curves, but averaging components would break the observed-curve guarantee,
so median.tf_mv returns the first tied curve (with a message). On tied
data, median(f)$x and median(f$x) can therefore differ.
## S3 method for class 'tf_mv' median(x, na.rm = FALSE, depth = "MBD", ...)## S3 method for class 'tf_mv' median(x, na.rm = FALSE, depth = "MBD", ...)
x |
a |
na.rm |
if |
depth |
the joint depth method, see |
... |
passed to |
a length-1 tf_mv: the observed curve with maximal joint depth.
Other tidyfun summary functions:
fivenum(),
functionwise,
tfsummaries
set.seed(1) f <- tfd_mv(list(x = tf_rgp(5), y = tf_rgp(5))) # the joint median is the observed curve with maximal joint depth: median(f) tf_depth(f)set.seed(1) f <- tfd_mv(list(x = tf_rgp(5), y = tf_rgp(5))) # the joint median is the observed curve with maximal joint depth: median(f) tf_depth(f)
Measurements of pinch force during 20 replications, with 151 observations recorded every 2 milliseconds over 300 milliseconds. The data captures the dynamics of finger pinch force applied during controlled motor tasks.
pinchpinch
A tfd vector of length 20 containing the pinch-force curves.
Data is also included in the fda package in another format.
Ramsay, O. J, Hooker, Giles, Graves, Spencer (2009). Functional Data Analysis with R and MATLAB, series Use R!, 1 edition. Springer New York, New York. ISBN 978-0-387-98184-0. doi:10.1007/978-0-387-98185-7.
Ramsay, O. J, Silverman, W. B (2005). Functional Data Analysis, series Springer Series in Statistics, 2nd edition. Springer, New York. ISBN 978-0-387-40080-8.
Ramsay, O. J, Silverman, W. B (2002). Applied Functional Data Analysis. Springer.
pinchpinch
base plots for tfsSome base functions for displaying functional data in
spaghetti- (i.e., line plots) and lasagna- (i.e., heat map) flavors.
## S3 method for class 'tf' plot( x, y, n_grid = 50, points = is_irreg(x), type = c("spaghetti", "lasagna"), alpha = min(1, max(0.05, 2/length(x))), ... ) ## S3 method for class 'tf' lines(x, arg, n_grid = 50, alpha = min(1, max(0.05, 2/length(x))), ...) ## S3 method for class 'tf' points( x, arg, n_grid = NA, alpha = min(1, max(0.05, 2/length(x))), interpolate = FALSE, ... )## S3 method for class 'tf' plot( x, y, n_grid = 50, points = is_irreg(x), type = c("spaghetti", "lasagna"), alpha = min(1, max(0.05, 2/length(x))), ... ) ## S3 method for class 'tf' lines(x, arg, n_grid = 50, alpha = min(1, max(0.05, 2/length(x))), ...) ## S3 method for class 'tf' points( x, arg, n_grid = NA, alpha = min(1, max(0.05, 2/length(x))), interpolate = FALSE, ... )
x |
a |
y |
(optional) numeric vector of evaluation points to use as |
n_grid |
minimal size of equidistant grid used for plotting,
defaults to |
points |
should the original evaluation points be marked by points?
Defaults to |
type |
|
alpha |
alpha-value (see |
... |
additional arguments for |
arg |
evaluation grid (vector). |
interpolate |
should functions be evaluated (i.e., inter-/extrapolated)
for arg for which no original data is available? Only relevant for
tfd, defaults to |
If no second argument y is given, evaluation points (arg) for the functions
are given by the union of the tf's arg and an equidistant grid
over its domain with n_grid points. If you want to only see the original
data for tfd-objects without inter-/extrapolation, use n_grid < 1 or
n_grid = NA.
the plotted tf-object, invisibly.
Swihart, J B, Caffo, Brian, James, D B, Strand, Matthew, Schwartz, S B, Punjabi, M N (2010). “Lasagna plots: a saucy alternative to spaghetti plots.” Epidemiology (Cambridge, Mass.), 21(5), 621–625.
f <- tfd(sin(seq(0, 2 * pi, length.out = 51)), arg = seq(0, 1, length.out = 51)) plot(f) plot(c(f, 2 * f), type = "lasagna")f <- tfd(sin(seq(0, 2 * pi, length.out = 51)), arg = seq(0, 1, length.out = 51)) plot(f) plot(c(f, 2 * f), type = "lasagna")
Two simple display modes for tf_mv objects: "facet" draws one panel per
output dimension (delegating to the univariate plot.tf());
"trajectory" (only for d == 2) draws the curves in the plane, i.e.
against – the natural view for movement data.
## S3 method for class 'tf_mv' plot(x, y, ..., type = NULL) ## S3 method for class 'tf_mv' lines(x, ..., type = NULL) ## S3 method for class 'tf_mv' points(x, ..., type = NULL)## S3 method for class 'tf_mv' plot(x, y, ..., type = NULL) ## S3 method for class 'tf_mv' lines(x, ..., type = NULL) ## S3 method for class 'tf_mv' points(x, ..., type = NULL)
x |
a |
y |
ignored. |
... |
passed to the underlying plotting calls. Per-curve graphical
parameters ( |
type |
|
In "trajectory" mode the two components must be paired at common argument
values to form points. When the components are sampled on
different (or per-curve irregular) grids they are therefore evaluated on the
union of their argument grids with interpolate = TRUE (values outside a
component's observed range become NA and are skipped). For components that
already share a grid this is a no-op.
x, invisibly.
Other tf_mv-class:
tf_arclength(),
tf_geom,
tf_mv_methods,
tfb_mfpc(),
tfb_mv(),
tfd_mv()
arg <- seq(0, 1, length.out = 31) xf <- tfd(t(sapply(1:5, function(i) sin(2 * pi * arg + i / 5))), arg = arg) yf <- tfd(t(sapply(1:5, function(i) cos(2 * pi * arg + i / 5))), arg = arg) mv <- tfd_mv(list(x = xf, y = yf)) plot(mv, type = "trajectory") plot(mv, type = "facet")arg <- seq(0, 1, length.out = 31) xf <- tfd(t(sapply(1:5, function(i) sin(2 * pi * arg + i / 5))), arg = arg) yf <- tfd(t(sapply(1:5, function(i) cos(2 * pi * arg + i / 5))), arg = arg) mv <- tfd_mv(list(x = xf, y = yf)) plot(mv, type = "trajectory") plot(mv, type = "facet")
(internal function exported for re-use in upstream packages)
prep_plotting_arg(f, n_grid)prep_plotting_arg(f, n_grid)
f |
a |
n_grid |
length of evaluation grid. |
a semi-regular grid rounded down to appropriate resolution.
f <- tfd(sin(seq(0, 2 * pi, length.out = 21)), arg = seq(0, 1, length.out = 21)) prep_plotting_arg(f, n_grid = 50)f <- tfd(sin(seq(0, 2 * pi, length.out = 21)), arg = seq(0, 1, length.out = 21)) prep_plotting_arg(f, n_grid = 50)
Prints and formats tf-objects for display. See details / examples for options that
give finer control.
## S3 method for class 'tf' print(x, n = 6, ...) ## S3 method for class 'tfd_reg' print(x, n = 6, ...) ## S3 method for class 'tfd_irreg' print(x, n = 6, ...) ## S3 method for class 'tfb' print(x, n = 5, ...) ## S3 method for class 'tf' format( x, digits = 2, nsmall = 0, width = options()$width, sparkline = TRUE, prefix = FALSE, ... )## S3 method for class 'tf' print(x, n = 6, ...) ## S3 method for class 'tfd_reg' print(x, n = 6, ...) ## S3 method for class 'tfd_irreg' print(x, n = 6, ...) ## S3 method for class 'tfb' print(x, n = 5, ...) ## S3 method for class 'tf' format( x, digits = 2, nsmall = 0, width = options()$width, sparkline = TRUE, prefix = FALSE, ... )
x |
any R object (conceptually); typically numeric. |
n |
how many elements of |
... |
handed over to |
digits |
a positive integer indicating how many significant digits
are to be used for
numeric and complex |
nsmall |
the minimum number of digits to the right of the decimal
point in formatting real/complex numbers in non-scientific formats.
Allowed values are |
width |
|
sparkline |
use a sparkline representation? defaults to |
prefix |
prefix with names / index positions? defaults to |
By default, tf objects on regular grids are shown as
"sparklines" (cli::spark_bar()), set sparkline = FALSE for a text
representation.
Sparklines are based on running mean values of the function values, but these don't check for non-equidistant grids, so the visual impression will be misleading for very unequal grid distances.
Sparklines use
options()$width/3 bins for printing/formatting by default, use bins
argument to set the number of bins explicitly.
For pillar::glimpse(), we use 8 bins by default for compact display.
print: prints out x and returns it invisibly.
a character representation of x.
t <- seq(0, 1, l = 201) cosine <- lapply(1:4, \(i) cos(i * pi * t)) |> tfd(arg = t) cosine tf_sparsify(cosine, dropout = .8) format(cosine, sparkline = FALSE) format(cosine, bins = 5) format(cosine, bins = 40) #! very non-equidistant grids --> sparklines can mislead about actual shapes: tfd(cosine, arg = t^3)t <- seq(0, 1, l = 201) cosine <- lapply(1:4, \(i) cos(i * pi * t)) |> tfd(arg = t) cosine tf_sparsify(cosine, dropout = .8) format(cosine, sparkline = FALSE) format(cosine, bins = 5) format(cosine, bins = 40) #! very non-equidistant grids --> sparklines can mislead about actual shapes: tfd(cosine, arg = t^3)
tf_align() applies the inverse warping function to unregistered data
to obtain aligned (registered) functions.
tf_align(x, warp, ...) ## S3 method for class 'tfd' tf_align(x, warp, ..., keep_new_arg = FALSE) ## S3 method for class 'tfb' tf_align(x, warp, ...)tf_align(x, warp, ...) ## S3 method for class 'tfd' tf_align(x, warp, ..., keep_new_arg = FALSE) ## S3 method for class 'tfb' tf_align(x, warp, ...)
x |
|
warp |
|
... |
additional arguments passed to |
keep_new_arg |
keep new |
the aligned tf vector (registered functions)
Other registration functions:
tf_estimate_warps(),
tf_landmarks_extrema(),
tf_register(),
tf_register_shape(),
tf_registration,
tf_warp()
# Estimate warps, then align manually: t <- seq(0, 2 * pi, length.out = 101) x <- tfd(t(sapply(c(-0.3, 0, 0.3), function(s) sin(t + s))), arg = t) warps <- tf_estimate_warps(x, method = "affine", type = "shift") aligned <- tf_align(x, warps) plot(aligned, col = 1:3)# Estimate warps, then align manually: t <- seq(0, 2 * pi, length.out = 101) x <- tfd(t(sapply(c(-0.3, 0, 0.3), function(s) sin(t + s))), arg = t) warps <- tf_estimate_warps(x, method = "affine", type = "shift") aligned <- tf_align(x, warps) plot(aligned, col = 1:3)
tfd-objectsThese are exported evaluator callbacks for tfd objects. They control how
function values are inter-/extrapolated to previously unseen arg values and
are used by tf_evaluate().
In typical use, set an evaluator when constructing a tfd
(tfd(..., evaluator = tf_approx_linear)) or replace it later via
tf_evaluator(x) <- tf_approx_none.
These helpers are wrappers around zoo::na.fill(), zoo::na.approx(), etc.
and all share the same signature (x, arg, evaluations), so they can
also be called directly.
The list:
tf_approx_linear for linear interpolation without extrapolation (i.e.,
zoo::na.approx() with na.rm = FALSE) – this is the default,
tf_approx_spline for cubic spline interpolation, (i.e., zoo::na.spline()
with na.rm = FALSE),
tf_approx_none in order to not inter-/extrapolate ever (i.e., zoo::na.fill() with fill = NA)
tf_approx_fill_extend for linear interpolation and constant extrapolation
(i.e., zoo::na.fill() with fill = "extend")
tf_approx_locf for "last observation carried forward" (i.e.,
zoo::na.locf() with na.rm = FALSE)
tf_approx_nocb for "next observation carried backward" (i.e.,
zoo::na.locf() with na.rm = FALSE, fromLast = TRUE).
For implementing your own, see source code of tf:::zoo_wrapper.
tf_approx_linear(x, arg, evaluations) tf_approx_spline(x, arg, evaluations) tf_approx_none(x, arg, evaluations) tf_approx_fill_extend(x, arg, evaluations) tf_approx_locf(x, arg, evaluations) tf_approx_nocb(x, arg, evaluations)tf_approx_linear(x, arg, evaluations) tf_approx_spline(x, arg, evaluations) tf_approx_none(x, arg, evaluations) tf_approx_fill_extend(x, arg, evaluations) tf_approx_locf(x, arg, evaluations) tf_approx_nocb(x, arg, evaluations)
x |
new |
arg |
the |
evaluations |
the function values at |
a vector of values of the function defined by the given
=(arg, evaluations)-tuples at new argument values x.
Other tidyfun inter/extrapolation functions:
tf_evaluate(),
tf_interpolate()
x <- tfd(matrix(c(0, 1), nrow = 1), arg = c(0, 1)) tf_evaluate(x, c(0, 0.5, 1)) tf_evaluator(x) <- tf_approx_none tf_evaluate(x, c(0, 0.5, 1)) tf_approx_linear( x = c(0, 0.5, 1), arg = c(0, 1), evaluations = c(0, 1) )x <- tfd(matrix(c(0, 1), nrow = 1), arg = c(0, 1)) tf_evaluate(x, c(0, 0.5, 1)) tf_evaluator(x) <- tf_approx_none tf_evaluate(x, c(0, 0.5, 1)) tf_approx_linear( x = c(0, 0.5, 1), arg = c(0, 1), evaluations = c(0, 1) )
For a vector-valued curve f: [a, b] -> R^d, the arc length is
– the length traced out by f in
R^d.
tf_arclength(f, ...) ## Default S3 method: tf_arclength(f, ...) ## S3 method for class 'tf_mv' tf_arclength( f, arg = NULL, lower = tf_domain(f)[1], upper = tf_domain(f)[2], definite = TRUE, method = c("polyline", "derive"), ... )tf_arclength(f, ...) ## Default S3 method: tf_arclength(f, ...) ## S3 method for class 'tf_mv' tf_arclength( f, arg = NULL, lower = tf_domain(f)[1], upper = tf_domain(f)[2], definite = TRUE, method = c("polyline", "derive"), ... )
f |
a |
... |
forwarded to |
arg, lower, upper
|
optional evaluation/integration grid and limits. |
definite |
|
method |
|
Two methods are supported:
"polyline" (default): sum of the Euclidean lengths of the line
segments between consecutive sample points (in R^d). Each curve is
evaluated on the union of its components' argument grids (or a supplied
arg) and the segment-sum is computed in closed form. For raw tfd_mv
data this is more accurate than "derive" because it avoids the
compounding error of numerical differentiation followed by quadrature.
"derive": composes the existing verbs – per-component
differentiation (tf_derive()), pointwise speed tf_speed(), then
tf_integrate(). Best for tfb_mv (analytical derivatives) or when a
custom tf_integrate(...) argument is needed.
a numeric vector (definite) or a univariate tfd (indefinite).
Other tf_mv-class:
plot.tf_mv(),
tf_geom,
tf_mv_methods,
tfb_mfpc(),
tfb_mv(),
tfd_mv()
# unit circle parameterised on [0, 1] -- arc length is 2*pi t <- seq(0, 1, length.out = 401) circ <- tfd_mv(list( x = tfd(matrix(cos(2 * pi * t), nrow = 1), arg = t), y = tfd(matrix(sin(2 * pi * t), nrow = 1), arg = t) )) tf_arclength(circ) tf_arclength(circ, lower = 0, upper = 0.25) # quarter -> pi/2 tf_arclength(circ, definite = FALSE) # cumulative s(t)# unit circle parameterised on [0, 1] -- arc length is 2*pi t <- seq(0, 1, length.out = 401) circ <- tfd_mv(list( x = tfd(matrix(cos(2 * pi * t), nrow = 1), arg = t), y = tfd(matrix(sin(2 * pi * t), nrow = 1), arg = t) )) tf_arclength(circ) tf_arclength(circ, lower = 0, upper = 0.25) # quarter -> pi/2 tf_arclength(circ, definite = FALSE) # cumulative s(t)
tf-objectsA bunch of methods & utilities that do what they say: get or set the
respective attributes of a tf-object.
is_tf_1d() distinguishes univariate tf vectors (length-n
samples of f: R -> R) from any tf vector. Returns TRUE for tfd /
tfb and FALSE for tfd_mv / tfb_mv. Useful as a dispatch / guard
predicate inside helpers that assume scalar per-arg evaluations.
tf_arg(f) tf_evaluations(f) tf_count(f) tf_domain(f) tf_domain(x) <- value tf_evaluator(f) tf_evaluator(x) <- value tf_basis(f, as_tfd = FALSE) tf_arg(x) <- value ## S3 replacement method for class 'tfd_irreg' tf_arg(x) <- value ## S3 replacement method for class 'tfd_reg' tf_arg(x) <- value ## S3 replacement method for class 'tfb' tf_arg(x) <- value ## S3 method for class 'tfb' coef(object, ...) ## S3 method for class 'tf' rev(x) ## S3 method for class 'tf_mv' rev(x) ## S3 method for class 'tf' is.na(x) ## S3 method for class 'tfd_irreg' is.na(x) is_tf(x) is_tf_1d(x) is_tfd(x) is_reg(x) is_tfd_reg(x) is_irreg(x) is_tfd_irreg(x) is_tfb(x) is_tfb_spline(x) is_tfb_fpc(x) is_tf_mv(x) is_tfd_mv(x) is_tfb_mv(x)tf_arg(f) tf_evaluations(f) tf_count(f) tf_domain(f) tf_domain(x) <- value tf_evaluator(f) tf_evaluator(x) <- value tf_basis(f, as_tfd = FALSE) tf_arg(x) <- value ## S3 replacement method for class 'tfd_irreg' tf_arg(x) <- value ## S3 replacement method for class 'tfd_reg' tf_arg(x) <- value ## S3 replacement method for class 'tfb' tf_arg(x) <- value ## S3 method for class 'tfb' coef(object, ...) ## S3 method for class 'tf' rev(x) ## S3 method for class 'tf_mv' rev(x) ## S3 method for class 'tf' is.na(x) ## S3 method for class 'tfd_irreg' is.na(x) is_tf(x) is_tf_1d(x) is_tfd(x) is_reg(x) is_tfd_reg(x) is_irreg(x) is_tfd_irreg(x) is_tfb(x) is_tfb_spline(x) is_tfb_fpc(x) is_tf_mv(x) is_tfd_mv(x) is_tfb_mv(x)
f |
an |
x |
an |
value |
for |
as_tfd |
should the basis be returned as a |
object |
a |
... |
not used. |
either the respective attribute or, for setters (assignment functions), the input object with modified properties.
Other tidyfun utility functions:
ensure_list(),
in_range(),
tf_zoom(),
unique_id()
x <- tf_rgp(3) tf_arg(x) tf_evaluations(x) tf_count(x) tf_domain(x) tf_evaluator(x) tf_evaluate(x, 0.25) tf_evaluator(x) <- tf_approx_none tf_evaluate(x, 0.25) c(is_tf(x), is_tfd(x), is_reg(x), is_irreg(x)) xb <- tfb(x, k = 4, penalized = FALSE, verbose = FALSE) tf_basis(xb) tf_basis(xb)(c(0, .1, .2)) c(is_tfb(xb), is_tfb_spline(xb), is_tfb_fpc(xb))x <- tf_rgp(3) tf_arg(x) tf_evaluations(x) tf_count(x) tf_domain(x) tf_evaluator(x) tf_evaluate(x, 0.25) tf_evaluator(x) <- tf_approx_none tf_evaluate(x, 0.25) c(is_tf(x), is_tfd(x), is_reg(x), is_irreg(x)) xb <- tfb(x, k = 4, penalized = FALSE, verbose = FALSE) tf_basis(xb) tf_basis(xb)(c(0, .1, .2)) c(is_tfb(xb), is_tfb_spline(xb), is_tfb_fpc(xb))
Data depths for functional data. All depths are scaled so that 1 means most central and 0 means most extreme. Available methods:
tf_depth(x, arg, depth = "MBD", na.rm = TRUE, ...) ## S3 method for class 'matrix' tf_depth( x, arg, depth = c("MBD", "MHI", "FM", "FSD", "RPD"), na.rm = TRUE, ... ) ## S3 method for class 'tf' tf_depth(x, arg, depth = "MBD", na.rm = TRUE, ...) ## S3 method for class 'tf_mv' tf_depth( x, arg, depth = c("MBD", "MHI", "FM", "FSD", "RPD"), na.rm = TRUE, weights = "equal", ... )tf_depth(x, arg, depth = "MBD", na.rm = TRUE, ...) ## S3 method for class 'matrix' tf_depth( x, arg, depth = c("MBD", "MHI", "FM", "FSD", "RPD"), na.rm = TRUE, ... ) ## S3 method for class 'tf' tf_depth(x, arg, depth = "MBD", na.rm = TRUE, ...) ## S3 method for class 'tf_mv' tf_depth( x, arg, depth = c("MBD", "MHI", "FM", "FSD", "RPD"), na.rm = TRUE, weights = "equal", ... )
x |
|
arg |
grid of evaluation points. |
depth |
one of |
na.rm |
remove missing observations? Defaults to |
... |
for |
weights |
( |
"MBD": Modified Band-2 Depth (default). Scale of 0 (most extreme) to
1 (most central).
"MHI": Modified Hypograph Index. Ranks functions from lowest (0) to
highest (1) instead of most extreme to most central! For functions that
never cross: .
"FM": Fraiman-Muniz depth. Integrates pointwise univariate halfspace
depths over the domain. Scale of 0 (most extreme) to 1 (most central).
"FSD": Functional Spatial Depth. Based on spatial signs; robust to
outliers. Scale of 0 (most extreme) to 1 (most central).
"RPD": Regularized Projection Depth. Projects curves onto random
directions and computes outlyingness. Especially useful for detecting
shape outliers. Scale of 0 (most extreme) to 1 (most central).
Note: results depend on the RNG state; set a seed
(e.g. set.seed(...)) before calling for reproducibility. Accepts
additional arguments via ...: u (quantile level for regularization,
default 0.01), n_projections (M, number of projection directions,
default 5000), n_projections_beta (L, directions for estimating
regularization parameter, default 500).
vector of depth values
Sun, Ying, Genton, G M, Nychka, W D (2012). “Exact fast computation of band depth for large functional datasets: How quickly can one million curves be ranked?” Stat, 1(1), 68–74.
López-Pintado, Sara, Romo, Juan (2009). “On the concept of depth for functional data.” Journal of the American Statistical Association, 104(486), 718–734.
López-Pintado, Sara, Romo, Juan (2011). “A half-region depth for functional data.” Computational Statistics & Data Analysis, 55(4), 1679–1695.
Fraiman, Ricardo, Muniz, Graciela (2001). “Trimmed means for functional data.” Test, 10(2), 419–440.
Chakraborty, Anirvan, Chaudhuri, Probal (2014). “The spatial distribution in infinite dimensional spaces and related quantiles and depths.” The Annals of Statistics, 42(3), 1203–1231.
Bočinec, Filip, Nagy, Stanislav, Yeon, Hyemin (2026). “Projection depth for functional data: Practical issues, computation and applications.” arXiv preprint arXiv:2602.22877.
Other tidyfun ordering and ranking functions:
tf_minmax,
tf_order()
x <- tf_rgp(3)/3 + 1:3 tf_depth(x, depth = "MBD") tf_depth(x, depth = "MHI") tf_depth(x, depth = "FM") tf_depth(x, depth = "FSD")x <- tf_rgp(3)/3 + 1:3 tf_depth(x, depth = "MBD") tf_depth(x, depth = "MHI") tf_depth(x, depth = "FM") tf_depth(x, depth = "FSD")
Derivatives of tf-objects use finite differences of the evaluations for
tfd and finite differences of the basis functions for tfb.
tf_derive(f, arg, order = 1, ...) ## S3 method for class 'matrix' tf_derive(f, arg, order = 1, ...) ## S3 method for class 'tfd' tf_derive(f, arg = tf_arg(f), order = 1, ...) ## S3 method for class 'tfd_irreg' tf_derive(f, arg, order = 1, ...) ## S3 method for class 'tfb_spline' tf_derive(f, arg = tf_arg(f), order = 1, ...) ## S3 method for class 'tfb_fpc' tf_derive(f, arg = tf_arg(f), order = 1, ...)tf_derive(f, arg, order = 1, ...) ## S3 method for class 'matrix' tf_derive(f, arg, order = 1, ...) ## S3 method for class 'tfd' tf_derive(f, arg = tf_arg(f), order = 1, ...) ## S3 method for class 'tfd_irreg' tf_derive(f, arg, order = 1, ...) ## S3 method for class 'tfb_spline' tf_derive(f, arg = tf_arg(f), order = 1, ...) ## S3 method for class 'tfb_fpc' tf_derive(f, arg = tf_arg(f), order = 1, ...)
f |
a |
arg |
grid to use for the finite differences. |
order |
order of differentiation. Maximal value for |
... |
not used |
The derivatives of tfd objects use second-order accurate central differences
for interior points and second-order accurate one-sided differences at
boundaries, following the non-uniform grid formulas from numpy.gradient
with edge_order=2 (Fornberg, 1988).
Domain and grid of the returned object are identical to the input. Unless the
tfd has a rather fine and regular grid, representing the data in a suitable
basis representation with tfb() and then computing the derivatives (or
integrals) of those is usually preferable.
Note that, for spline bases like "cr" or "tp" which are constrained to
begin/end linearly, computing second derivatives will produce artefacts at
the outer limits of the functions' domain due to these boundary constraints.
Basis "bs" does not have this problem for sufficiently high orders (but
tends to yield slightly less stable fits).
a tf (with the same arg for tfd-inputs, possibly different
basis for tfb-inputs, see details).
tf_derive(matrix): row-wise finite differences
tf_derive(tfd): derivatives by finite differencing of function evaluations.
tf_derive(tfd_irreg): element-wise finite differencing for irregular grids.
Falls back to tf_derive.tfd (interpolating to a common grid) if an
explicit arg vector is supplied.
tf_derive(tfb_spline): derivatives by finite differencing of spline basis functions.
tf_derive(tfb_fpc): derivatives by finite differencing of FPC basis functions.
Fornberg, Bengt (1988). “Generation of Finite Difference Formulas on Arbitrarily Spaced Grids.” Mathematics of Computation, 51(184), 699–706.
Other tidyfun calculus functions:
tf_integrate()
arg <- seq(0, 1, length.out = 31) x <- tfd(rbind(arg^2, sin(2 * pi * arg)), arg = arg) dx <- tf_derive(x) x dx tf_arg(dx)arg <- seq(0, 1, length.out = 31) x <- tfd(rbind(arg^2, sin(2 * pi * arg)), arg = arg) dx <- tf_derive(x) x dx tf_arg(dx)
tf_estimate_warps() is the low-level workhorse for functional data
registration. It estimates warping functions that align a set of functions to
a template, but does not apply them. For a one-shot interface that also
aligns the data, see tf_register().
tf_estimate_warps( x, ..., template = NULL, method = c("srvf", "srvf_mv", "cc", "affine", "landmark"), max_iter = 3L, tol = 0.01 )tf_estimate_warps( x, ..., template = NULL, method = c("srvf", "srvf_mv", "cc", "affine", "landmark"), max_iter = 3L, tol = 0.01 )
x |
a |
... |
additional method-specific arguments passed to backend routines
(for example |
template |
an optional |
method |
the registration method to use:
|
max_iter |
integer: maximum number of Procrustes-style template
refinement iterations when |
tol |
numeric: convergence tolerance for template refinement. For
|
For method = "cc", tf uses a tf-native dense-grid optimizer with
monotone spline warps. Each warp is represented as the normalized cumulative
integral of exp(eta(t)), where eta(t) is a spline with nbasis
coefficients. Registration is then carried out curve-by-curve by minimizing
either an integrated squared-error criterion (crit = 1) or the
first-eigenfunction variance criterion (crit = 2) plus an optional spline
roughness penalty (lambda). The outer max_iter loop, when template = NULL, still performs the same Procrustes-style template refinement as the
other methods.
tfd vector of (forward) warping functions
with the same length as x.
Apply with tf_align() to obtain registered functions, or use
tf_invert() to obtain inverse warps .
The returned warps carry an attr(, "template") with the template used
(NULL for landmark registration, which has no template).
...)For method = "srvf":
lambdanon-negative number: penalty controlling the flexibility of
warpings (default is 0 for unrestricted warps).
penalty_methodcost function used to penalize warping functions.
Defaults to "roughness" (norm of their second derivative),
"geodesic" uses the geodesic distance to the identity and "norm" uses
Euclidean distance to the identity.
For method = "cc":
nbasisinteger: number of B-spline basis functions for the monotone
warp basis (default 6L, minimum 2).
lambdanon-negative number: roughness penalty for the warp basis
(default 0 for unpenalized warping).
critregistration criterion. Defaults to 2 for the
first-eigenfunction variance criterion; alternative is 1 for
integrated squared error.
convnon-negative convergence tolerance for the inner optimizer.
Default is 1e-4.
iterlimmaximum number of inner optimization iterations per curve.
Default is 20L.
For method = "affine":
typecharacter: "shift" (translation only), "scale" (scaling only),
or "shift_scale" (both). Default is "shift".
shift_rangenumeric(2): bounds for shift parameter. Default is
c(-range/2, range/2) where range is the domain width.
Larger bounds allow greater shifts but may result in more NA values.
scale_rangenumeric(2): bounds for scale parameter. Default is
c(0.5, 2). Must have lower > 0.
For method = "landmark":
landmarks(required) numeric matrix of landmark positions with
one row per function and one column per landmark. Use tf_landmarks_extrema()
to find peaks/valleys automatically.
template_landmarksnumeric vector of target landmark positions.
Default is column-wise mean of landmarks.
Maximilian Muecke, Fabian Scheipl, Claude Opus 4.6
Other registration functions:
tf_align(),
tf_landmarks_extrema(),
tf_register(),
tf_register_shape(),
tf_registration,
tf_warp()
# see tf_register() for full registration examples set.seed(1) f <- tf_rgp(5) warps <- tf_estimate_warps(f, method = "srvf") plot(warps)# see tf_register() for full registration examples set.seed(1) f <- tf_rgp(5) warps <- tf_estimate_warps(f, method = "srvf") plot(warps)
tf-vectors for given argument valuesAlso used internally by the [-operator for tf data (see ?tfbrackets) to
evaluate object, see examples.
tf_evaluate(object, arg, ...) ## Default S3 method: tf_evaluate(object, arg, ...) ## S3 method for class 'tfd' tf_evaluate(object, arg, evaluator = tf_evaluator(object), ...) ## S3 method for class 'tfb' tf_evaluate(object, arg, ...)tf_evaluate(object, arg, ...) ## Default S3 method: tf_evaluate(object, arg, ...) ## S3 method for class 'tfd' tf_evaluate(object, arg, evaluator = tf_evaluator(object), ...) ## S3 method for class 'tfb' tf_evaluate(object, arg, ...)
object |
a |
arg |
optional evaluation grid (vector or list of vectors).
Defaults to |
... |
not used. |
evaluator |
optional. The function to use for inter/extrapolating the
|
A list of numeric vectors containing the function
evaluations on arg.
Other tidyfun inter/extrapolation functions:
tf_approx_linear(),
tf_interpolate()
f <- tf_rgp(3, arg = seq(0, 1, length.out = 11)) tf_evaluate(f) |> str() tf_evaluate(f, arg = 0.5) |> str() # equivalent, as matrix: f[, 0.5] new_grid <- seq(0, 1, length.out = 6) tf_evaluate(f, arg = new_grid) |> str() # equivalent, as matrix: f[, new_grid]f <- tf_rgp(3, arg = seq(0, 1, length.out = 11)) tf_evaluate(f) |> str() tf_evaluate(f, arg = 0.5) |> str() # equivalent, as matrix: f[, 0.5] new_grid <- seq(0, 1, length.out = 6) tf_evaluate(f, arg = new_grid) |> str() # equivalent, as matrix: f[, new_grid]
Small geometric helpers defined by component-wise composition of the existing
univariate Ops / Math machinery:
tf_norm(f) – pointwise Euclidean norm ;
tf_speed(f) – pointwise speed ;
tf_inner(f, g) – pointwise inner product ;
tf_distance(f, g) – pointwise Euclidean distance ;
tf_tangent(f) – unit tangent
(undefined where the speed is zero – callers get NaNs there);
tf_reparam_arclength(f) – re-parametrize the curve at constant speed
(i.e. by its normalized cumulative arc length).
tf_norm(f) ## Default S3 method: tf_norm(f) ## S3 method for class 'tf' tf_norm(f) ## S3 method for class 'tf_mv' tf_norm(f) tf_speed(f) tf_inner(f, g) ## Default S3 method: tf_inner(f, g) ## S3 method for class 'tf' tf_inner(f, g) ## S3 method for class 'tf_mv' tf_inner(f, g) tf_distance(f, g) tf_tangent(f) ## Default S3 method: tf_tangent(f) ## S3 method for class 'tf' tf_tangent(f) ## S3 method for class 'tf_mv' tf_tangent(f) tf_reparam_arclength(f)tf_norm(f) ## Default S3 method: tf_norm(f) ## S3 method for class 'tf' tf_norm(f) ## S3 method for class 'tf_mv' tf_norm(f) tf_speed(f) tf_inner(f, g) ## Default S3 method: tf_inner(f, g) ## S3 method for class 'tf' tf_inner(f, g) ## S3 method for class 'tf_mv' tf_inner(f, g) tf_distance(f, g) tf_tangent(f) ## Default S3 method: tf_tangent(f) ## S3 method for class 'tf' tf_tangent(f) ## S3 method for class 'tf_mv' tf_tangent(f) tf_reparam_arclength(f)
f, g
|
|
These also apply to univariate tfd/tfb (treated as scalar-valued curves
), where they reduce to their one-dimensional
specializations: ,
, and the unit tangent
.
a univariate tfd for tf_norm/tf_speed/tf_inner/tf_distance;
tf_tangent returns a tf_mv (or a univariate tf for univariate input)
and tf_reparam_arclength a tf_mv.
Other tf_mv-class:
plot.tf_mv(),
tf_arclength(),
tf_mv_methods,
tfb_mfpc(),
tfb_mv(),
tfd_mv()
set.seed(1) f <- tfd_mv(list(x = tf_rgp(2), y = tf_rgp(2))) tf_norm(f) tf_speed(f) tf_distance(f, tfd_mv(list(x = tf_rgp(2), y = tf_rgp(2)))) # univariate: tf_norm reduces to the pointwise absolute value u <- tf_rgp(2) tf_norm(u) tf_inner(u, tf_rgp(2))set.seed(1) f <- tfd_mv(list(x = tf_rgp(2), y = tf_rgp(2))) tf_norm(f) tf_speed(f) tf_distance(f, tfd_mv(list(x = tf_rgp(2), y = tf_rgp(2)))) # univariate: tf_norm reduces to the pointwise absolute value u <- tf_rgp(2) tf_norm(u) tf_inner(u, tf_rgp(2))
Integrals of tf-objects are computed by simple quadrature (trapezoid rule).
By default the scalar definite integral
is returned (option definite = TRUE),
alternatively for definite = FALSE the anti-derivative on
[lower, upper], e.g. a tfd or tfb object representing , for [lower, upper], is returned.
tf_integrate(f, arg, lower, upper, ...) ## Default S3 method: tf_integrate(f, arg, lower, upper, ...) ## S3 method for class 'tfd' tf_integrate( f, arg = tf_arg(f), lower = tf_domain(f)[1], upper = tf_domain(f)[2], definite = TRUE, ... ) ## S3 method for class 'tfb' tf_integrate( f, arg = tf_arg(f), lower = tf_domain(f)[1], upper = tf_domain(f)[2], definite = TRUE, ... )tf_integrate(f, arg, lower, upper, ...) ## Default S3 method: tf_integrate(f, arg, lower, upper, ...) ## S3 method for class 'tfd' tf_integrate( f, arg = tf_arg(f), lower = tf_domain(f)[1], upper = tf_domain(f)[2], definite = TRUE, ... ) ## S3 method for class 'tfb' tf_integrate( f, arg = tf_arg(f), lower = tf_domain(f)[1], upper = tf_domain(f)[2], definite = TRUE, ... )
f |
a |
arg |
(optional) grid to use for the quadrature. |
lower |
lower limits of the integration range. For |
upper |
upper limits of the integration range (but see |
... |
not used |
definite |
should the definite integral be returned (default) or the antiderivative. See description. |
When f is irregular and lower / upper are not supplied explicitly,
they default to each curve's own observed arg range (i.e., the range of its
tf_arg() values) rather than the (shared) domain endpoints; for regular tfd
the defaults remain the domain endpoints.
Without this per-curve default, curves that do not span the full domain
would silently NA-poison the trapezoidal sum, because the default linear
evaluator does not extrapolate. Pass explicit lower / upper to integrate
over a fixed sub-interval, or switch to an extrapolating evaluator
(e.g. tf_approx_fill_extend()) to integrate over the full domain.
For definite = TRUE, the definite integrals of the functions in
f. For definite = FALSE and tf-inputs, a tf object containing their
anti-derivatives
Other tidyfun calculus functions:
tf_derive()
arg <- seq(0, 1, length.out = 11) x <- tfd(rbind(arg, arg^2), arg = arg) tf_integrate(x) anti <- tf_integrate(x, definite = FALSE) tf_arg(anti)arg <- seq(0, 1, length.out = 11) x <- tfd(rbind(arg, arg^2), arg = arg) tf_integrate(x) anti <- tf_integrate(x, definite = FALSE) tf_arg(anti)
tf-objects on a new grid of argument values.Change the internal representation of a tf-object so that it
uses a different grid of argument values (arg). Useful for
thinning out dense grids to make data smaller
filling out sparse grids to make derivatives/integrals and locating extrema or zero crossings more accurate (... if the interpolation works well ...)
making irregular functional data into (more) regular data.
For tfd-objects, this is just syntactic sugar for tfd(object, arg = arg).
To inter/extrapolate more reliably and avoid NAs, call
tf_interpolate with evaluator = tf_approx_fill_extend.
For tfb-objects, this re-evaluates basis functions on the new grid which can
speed up subsequent computations if they all use that grid.
NB: To reliably impute very irregular data on a regular, common grid,
you'll be better off doing FPCA-based imputation or other model-based
approaches in most cases.
tf_interpolate(object, arg, ...) ## S3 method for class 'tfb' tf_interpolate(object, arg, ...) ## S3 method for class 'tfd' tf_interpolate(object, arg, ...) ## S3 method for class 'tf_mv' tf_interpolate(object, arg, ...)tf_interpolate(object, arg, ...) ## S3 method for class 'tfb' tf_interpolate(object, arg, ...) ## S3 method for class 'tfd' tf_interpolate(object, arg, ...) ## S3 method for class 'tf_mv' tf_interpolate(object, arg, ...)
object |
an object inheriting from |
arg |
a vector of argument values on which to evaluate the functions in
|
... |
additional arguments handed over to |
a tfd or tfb object on the new grid given by arg.
tf_rebase(), which is more general.
Other tidyfun inter/extrapolation functions:
tf_approx_linear(),
tf_evaluate()
# thinning out a densely observed tfd dense <- tf_rgp(10, arg = seq(0, 1, length.out = 1001)) less_dense <- tf_interpolate(dense, arg = seq(0, 1, length.out = 101)) dense less_dense # filling out sparse data (use a suitable evaluator-function!) sparse <- tf_rgp(10, arg = seq(0, 5, length.out = 11)) plot(sparse, points = TRUE) # change evaluator for better interpolation tfd(sparse, evaluator = tf_approx_spline) |> tf_interpolate(arg = seq(0, 5, length.out = 201)) |> lines(col = 2, lty = 2) set.seed(1860) sparse_irregular <- tf_rgp(5) |> tf_sparsify(0.5) |> tf_jiggle() tf_interpolate(sparse_irregular, arg = seq(0, 1, length.out = 51))# thinning out a densely observed tfd dense <- tf_rgp(10, arg = seq(0, 1, length.out = 1001)) less_dense <- tf_interpolate(dense, arg = seq(0, 1, length.out = 101)) dense less_dense # filling out sparse data (use a suitable evaluator-function!) sparse <- tf_rgp(10, arg = seq(0, 5, length.out = 11)) plot(sparse, points = TRUE) # change evaluator for better interpolation tfd(sparse, evaluator = tf_approx_spline) |> tf_interpolate(arg = seq(0, 5, length.out = 201)) |> lines(col = 2, lty = 2) set.seed(1860) sparse_irregular <- tf_rgp(5) |> tf_sparsify(0.5) |> tf_jiggle() tf_interpolate(sparse_irregular, arg = seq(0, 1, length.out = 51))
tf vectorComputes the functional inverse of each function in the tf vector, such that
if , then .
tf_invert(x, ...)tf_invert(x, ...)
x |
a |
... |
optional arguments for the returned object, see |
a tf vector of the inverted functions.
arg <- seq(0, 2, length.out = 50) x <- tfd(rbind(2 * arg, arg^2), arg = arg) x_inv <- tf_invert(x) layout(t(1:2)) plot(x, main = "original functions", ylab = "") plot(x_inv, main = "inverted functions", ylab = "", points = FALSE)arg <- seq(0, 2, length.out = 50) x <- tfd(rbind(2 * arg, arg^2), arg = arg) x_inv <- tf_invert(x) layout(t(1:2)) plot(x, main = "original functions", ylab = "") plot(x_inv, main = "inverted functions", ylab = "", points = FALSE)
tf (more) irregularRandomly create some irregular functional data from regular ones.
jiggle it by randomly moving around its arg-values inside the intervals defined by its grid neighbors on the original argument grid.
sparsify it by removing (100*dropout)% of the function values
tf_jiggle(f, amount = 0.4, ...) ## S3 method for class 'tf_mv' tf_jiggle(f, amount = 0.4, same_arg = TRUE, ...) tf_sparsify(f, dropout = 0.5, ...) ## S3 method for class 'tf_mv' tf_sparsify(f, dropout = 0.5, same_arg = TRUE, ...)tf_jiggle(f, amount = 0.4, ...) ## S3 method for class 'tf_mv' tf_jiggle(f, amount = 0.4, same_arg = TRUE, ...) tf_sparsify(f, dropout = 0.5, ...) ## S3 method for class 'tf_mv' tf_sparsify(f, dropout = 0.5, same_arg = TRUE, ...)
f |
a |
amount |
how far away from original grid points can the jiggled grid points lie, at most (relative to original distance to neighboring grid points). Defaults to at most 40% (0.4) of the original grid distances. Must be lower than 0.5. |
... |
additional args for the returned |
same_arg |
for |
dropout |
what proportion of values of |
an (irregular) tfd object.
Other tidyfun RNG functions:
tf_rgp()
set.seed(1) (x <- tf_rgp(2, arg = 21L)) (x_jig <- tf_jiggle(x, amount = 0.2)) (x_sp <- tf_sparsify(x, dropout = 0.3)) c(is_irreg(x_jig), is_irreg(x_sp))set.seed(1) (x <- tf_rgp(2, arg = 21L)) (x_jig <- tf_jiggle(x, amount = 0.2)) (x_sp <- tf_sparsify(x, dropout = 0.3)) c(is_irreg(x_jig), is_irreg(x_sp))
Find landmark locations for registration
tf_landmarks_extrema(x, which = "all", threshold = 0.5, boundary_tol = NULL)tf_landmarks_extrema(x, which = "all", threshold = 0.5, boundary_tol = NULL)
x |
a |
which |
character: which features to detect. Either |
threshold |
numeric in (0, 1]: minimum proportion of curves that must
contain a feature for it to be retained as a landmark. Defaults to |
boundary_tol |
numeric: features within this distance of the domain
boundary are dropped (they are redundant with the boundary anchors in
landmark registration). Defaults to 2x the grid spacing. Set to |
Detects local maxima, minima, and/or zero crossings in each function and
returns a landmark matrix suitable for tf_register() with
method = "landmark". Uses position-based clustering across curves to
establish feature correspondence and majority-count filtering to discard
unstable landmarks.
A numeric matrix with one row per function and one column per
landmark, sorted left-to-right on the domain. Has attribute
"feature_types" (character vector of "max", "min", or "zero" for
each column). Contains NA where a curve is missing a landmark.
tf_register() with method = "landmark"
Other registration functions:
tf_align(),
tf_estimate_warps(),
tf_register(),
tf_register_shape(),
tf_registration,
tf_warp()
t <- seq(0, 1, length.out = 101) x <- tfd(t(sapply(c(0.3, 0.5, 0.7), function(s) dnorm(t, s, 0.1))), arg = t) tf_landmarks_extrema(x, "max") tf_landmarks_extrema(x, "both")t <- seq(0, 1, length.out = 101) x <- tfd(t(sapply(c(0.3, 0.5, 0.7), function(s) dnorm(t, s, 0.1))), arg = t) tf_landmarks_extrema(x, "max") tf_landmarks_extrema(x, "both")
tf vectorsBy default, min, max, and range compute pointwise extremes (the
existing behaviour). When a depth argument is supplied, they instead return
the most extreme / most central observation according to the chosen depth.
For the default "MHI" depth this gives the lowest / highest function in an
up-down sense.
## S3 method for class 'tf' min(..., na.rm = FALSE, depth = NULL) ## S3 method for class 'tf' max(..., na.rm = FALSE, depth = NULL) ## S3 method for class 'tf' range(..., na.rm = FALSE, depth = NULL)## S3 method for class 'tf' min(..., na.rm = FALSE, depth = NULL) ## S3 method for class 'tf' max(..., na.rm = FALSE, depth = NULL) ## S3 method for class 'tf' range(..., na.rm = FALSE, depth = NULL)
... |
|
na.rm |
logical; passed on to the pointwise summary or used to filter
|
depth |
depth method to use. |
a tf object.
Other tidyfun ordering and ranking functions:
tf_depth(),
tf_order()
x <- tf_rgp(5) + 1:5 # pointwise (default): min(x) max(x) # depth-based: min(x, depth = "MHI") max(x, depth = "MHI")x <- tf_rgp(5) + 1:5 # pointwise (default): min(x) max(x) # depth-based: min(x, depth = "MHI") max(x, depth = "MHI")
Utilities for tf_mv objects (see tfd_mv() / tfb_mv()). tf_ncomp()
returns the number of output dimensions , tf_components() the list
of the d underlying univariate tf vectors, and tf_component() extracts
or replaces a single one (also available via the $ operator, e.g. f$x).
tf_ncomp(f) tf_components(f) tf_component(f, which) tf_component(f, which) <- valuetf_ncomp(f) tf_components(f) tf_component(f, which) tf_component(f, which) <- value
f |
a |
which |
a component name or index. |
value |
a univariate |
Most univariate tf verbs also work on tf_mv objects by acting on each
component: tf_rebase() (and hence tfd_mv/tfb_mv conversion),
tf_derive(), tf_integrate() (definite integrals return an n x d
matrix), tf_smooth() and tf_zoom(). Registration
(tf_register() / tf_estimate_warps() / tf_warp() / tf_align())
estimates a single, shared time-warp per curve and applies it jointly to
every component. The registration signal is, by default, the first
component; use ref_component to pick another component (by name/index),
"norm" for the pointwise Euclidean norm, or a function mapping the
tf_mv to a univariate tf vector.
is.na() flags a curve as missing if any of its components is missing
(the union, not the intersection), which also drives the na.rm behaviour
of mean() / median() etc.
tf_ncomp(): an integer. tf_components(): a named list of tf
vectors. tf_component(): a single univariate tf vector.
Other tf_mv-class:
plot.tf_mv(),
tf_arclength(),
tf_geom,
tfb_mfpc(),
tfb_mv(),
tfd_mv()
f <- tfd_mv(list(x = tf_rgp(3), y = tf_rgp(3))) tf_ncomp(f) tf_components(f) tf_component(f, "y") f$yf <- tfd_mv(list(x = tf_rgp(3), y = tf_rgp(3))) tf_ncomp(f) tf_components(f) tf_component(f, "y") f$y
tf vectorsThese methods use tf_depth() to rank, order, and sort functional data. By
default they use the modified hypograph index ("MHI") which provides an
up-down ordering (lowest to highest). You can also use any of the other depth
methods available via tf_depth(), or supply a custom depth function.
rank( x, na.last = TRUE, ties.method = c("average", "first", "last", "random", "max", "min"), ... ) ## Default S3 method: rank( x, na.last = TRUE, ties.method = c("average", "first", "last", "random", "max", "min"), ... ) ## S3 method for class 'tf' rank( x, na.last = TRUE, ties.method = c("average", "first", "last", "random", "max", "min"), depth = "MHI", ... ) ## S3 method for class 'tf' xtfrm(x) ## S3 method for class 'tf' sort(x, decreasing = FALSE, na.last = NA, depth = "MHI", ...) tf_order(f, ...) ## Default S3 method: tf_order(f, ...) ## S3 method for class 'tf' tf_order(f, depth = "MHI", ...) ## S3 method for class 'tf_mv' tf_order(f, by = "norm", ...)rank( x, na.last = TRUE, ties.method = c("average", "first", "last", "random", "max", "min"), ... ) ## Default S3 method: rank( x, na.last = TRUE, ties.method = c("average", "first", "last", "random", "max", "min"), ... ) ## S3 method for class 'tf' rank( x, na.last = TRUE, ties.method = c("average", "first", "last", "random", "max", "min"), depth = "MHI", ... ) ## S3 method for class 'tf' xtfrm(x) ## S3 method for class 'tf' sort(x, decreasing = FALSE, na.last = NA, depth = "MHI", ...) tf_order(f, ...) ## Default S3 method: tf_order(f, ...) ## S3 method for class 'tf' tf_order(f, depth = "MHI", ...) ## S3 method for class 'tf_mv' tf_order(f, by = "norm", ...)
x |
a |
na.last |
for handling of |
ties.method |
a character string for handling ties; see |
... |
passed to |
depth |
the depth function to use for ranking. One of the depths
available via |
decreasing |
logical. Should the sort be decreasing? |
f |
a |
by |
( |
rank assigns ranks based on depth values: lower depth values get lower
ranks. For "MHI" this gives an ordering from lowest to highest function.
For centrality-based depths ("MBD", "FM", "FSD", "RPD"), the most
extreme function gets rank 1 and the most central gets the highest rank.
tf_order returns the permutation which rearranges x into ascending
order according to depth. For vector-valued (tf_mv) data there is no
canonical total order on : tf_order.tf_mv() requires an explicit
scalar reduction via by (either "norm" for tf_norm(f), or a component
name), and then applies the univariate depth order to that reduction.
sort.tf returns the sorted tf vector.
xtfrm.tf returns a numeric vector of MHI depth values, enabling
base::order and base::rank to work on tf vectors.
rank: a numeric vector of ranks.tf_order: an integer vector of indices.sort.tf: a sorted tf vector.xtfrm.tf: a numeric vector of depth values.
tf_depth(), min.tf(), max.tf()
Other tidyfun ordering and ranking functions:
tf_depth(),
tf_minmax
x <- tf_rgp(5) + 1:5 rank(x) order(x) sort(x) # use a centrality-based depth instead: rank(x, depth = "MBD")x <- tf_rgp(5) + 1:5 rank(x) order(x) sort(x) # use a centrality-based depth instead: rank(x, depth = "MBD")
tf-objectApply the representation of one tf-object to another; i.e. re-express it in
the other's basis, on its grid, etc.
Useful for making different functional data objects compatible so they can
be combined, compared or computed with.
tf_rebase(object, basis_from, arg = tf_arg(basis_from), ...) ## S3 method for class 'tfd' tf_rebase(object, basis_from, arg = tf_arg(basis_from), ...) ## S3 method for class 'tfb' tf_rebase(object, basis_from, arg = tf_arg(basis_from), ...)tf_rebase(object, basis_from, arg = tf_arg(basis_from), ...) ## S3 method for class 'tfd' tf_rebase(object, basis_from, arg = tf_arg(basis_from), ...) ## S3 method for class 'tfb' tf_rebase(object, basis_from, arg = tf_arg(basis_from), ...)
object |
a |
basis_from |
the |
arg |
optional new |
... |
forwarded to the |
This uses double dispatch (S3) internally, so the methods defined below are
themselves generics for methods tf_rebase.tfd.tfd,
tf_rebase.tfd.tfb_spline, tf_rebase.tfd.tfb_fpc, tf_rebase.tfb.tfd,
tf_rebase.tfb.tfb that dispatch on object_from.
a tf-vector containing the data of object in the same representation
as basis_from (potentially modified by the arguments given in ...).
tf_rebase(tfd): re-express a tfd-vector in the same representation as
some other tf-vector
tf_rebase(tfb): re-express a tfb-vector in the same representation as
some other tf-vector.
x <- tf_rgp(3) xb <- tfb(x, k = 8, penalized = FALSE, verbose = FALSE) tf_rebase(tf_rgp(3), xb)x <- tf_rgp(3) xb <- tfb(x, k = 8, penalized = FALSE, verbose = FALSE) tf_rebase(tf_rgp(3), xb)
tf vector against a template functiontf_register() is the high-level entry point for functional data registration.
It estimates warping functions, applies them to align the data, and returns a
tf_registration result object containing the aligned curves, inverse
warping functions (observed to aligned time), and template. Use
tf_aligned(), tf_inv_warps(), and tf_template() to extract components.
tf_register( x, ..., template = NULL, method = c("srvf", "srvf_mv", "cc", "affine", "landmark"), max_iter = 3L, tol = 0.01, store_x = TRUE )tf_register( x, ..., template = NULL, method = c("srvf", "srvf_mv", "cc", "affine", "landmark"), max_iter = 3L, tol = 0.01, store_x = TRUE )
x |
a |
... |
additional method-specific arguments passed to backend routines
(for example |
template |
an optional |
method |
the registration method to use:
|
max_iter |
integer: maximum Procrustes-style template refinement
iterations. Default |
tol |
numeric: convergence tolerance for template refinement.
Default |
store_x |
logical: store original data in the result object?
Default |
For a lower-level interface that returns only warping functions (without
performing alignment), see tf_estimate_warps().
A tf_registration object. Access components with
tf_aligned(), tf_inv_warps(), tf_template().
...)For method = "srvf":
lambdanon-negative number: penalty controlling the flexibility of
warpings (default is 0 for unrestricted warps).
penalty_methodcost function used to penalize warping functions.
Defaults to "roughness" (norm of their second derivative),
"geodesic" uses the geodesic distance to the identity and "norm" uses
Euclidean distance to the identity.
For method = "cc":
nbasisinteger: number of B-spline basis functions for the monotone
warp basis (default 6L, minimum 2).
lambdanon-negative number: roughness penalty for the warp basis
(default 0 for unpenalized warping).
critregistration criterion. Defaults to 2 for the
first-eigenfunction variance criterion; alternative is 1 for
integrated squared error.
convnon-negative convergence tolerance for the inner optimizer.
Default is 1e-4.
iterlimmaximum number of inner optimization iterations per curve.
Default is 20L.
For method = "affine":
typecharacter: "shift" (translation only), "scale" (scaling only),
or "shift_scale" (both). Default is "shift".
shift_rangenumeric(2): bounds for shift parameter. Default is
c(-range/2, range/2) where range is the domain width.
Larger bounds allow greater shifts but may result in more NA values.
scale_rangenumeric(2): bounds for scale parameter. Default is
c(0.5, 2). Must have lower > 0.
For method = "landmark":
landmarks(required) numeric matrix of landmark positions with
one row per function and one column per landmark. Use tf_landmarks_extrema()
to find peaks/valleys automatically.
template_landmarksnumeric vector of target landmark positions.
Default is column-wise mean of landmarks.
Maximilian Muecke, Fabian Scheipl, Claude Opus 4.6
Ramsay JO, Hooker G, Graves S (2009). Functional Data Analysis with R and MATLAB. Springer, New York. doi:10.1007/978-0-387-98185-7.
Srivastava A, Wu W, Kurtek S, Klassen E, Marron JS (2011). "Registration of Functional Data Using Fisher-Rao Metric." arXiv:1103.3817.
Tucker JD, Wu W, Srivastava A (2013). "Generative models for functional data using phase and amplitude separation." Computational Statistics & Data Analysis, 61, 50–66. doi:10.1016/j.csda.2012.12.001.
Other registration functions:
tf_align(),
tf_estimate_warps(),
tf_landmarks_extrema(),
tf_register_shape(),
tf_registration,
tf_warp()
# Elastic registration (SRVF method) height_female <- subset(growth, gender == "female", select = height, drop = TRUE) growth_female <- tf_derive(height_female) |> tfd(arg = seq(1.125, 17.8), l = 101) reg <- tf_register(growth_female) layout(t(1:3)) plot(growth_female, xlab = "Chronological Age", ylab = "Growth Rate (cm/year)") plot(tf_inv_warps(reg), xlab = "Chronological Age", ylab = "Biological Age") plot(tf_aligned(reg), xlab = "Biological Age", ylab = "Growth Rate (cm/year)") # Affine registration (shift only) t <- seq(0, 2 * pi, length.out = 101) x <- tfd(t(sapply(c(-0.3, 0, 0.3), function(s) sin(t + s))), arg = t) reg <- tf_register(x, method = "affine", type = "shift") plot(tf_aligned(reg), col = 1:3) # Landmark registration peaks <- tf_landmarks_extrema(x, "max") reg <- tf_register(x, method = "landmark", landmarks = peaks) plot(tf_aligned(reg), col = 1:3)# Elastic registration (SRVF method) height_female <- subset(growth, gender == "female", select = height, drop = TRUE) growth_female <- tf_derive(height_female) |> tfd(arg = seq(1.125, 17.8), l = 101) reg <- tf_register(growth_female) layout(t(1:3)) plot(growth_female, xlab = "Chronological Age", ylab = "Growth Rate (cm/year)") plot(tf_inv_warps(reg), xlab = "Chronological Age", ylab = "Biological Age") plot(tf_aligned(reg), xlab = "Biological Age", ylab = "Growth Rate (cm/year)") # Affine registration (shift only) t <- seq(0, 2 * pi, length.out = 101) x <- tfd(t(sapply(c(-0.3, 0, 0.3), function(s) sin(t + s))), arg = t) reg <- tf_register(x, method = "affine", type = "shift") plot(tf_aligned(reg), col = 1:3) # Landmark registration peaks <- tf_landmarks_extrema(x, "max") reg <- tf_register(x, method = "landmark", landmarks = peaks) plot(tf_aligned(reg), col = 1:3)
tf_register_shape() aligns vector-valued tf_mv curves with SRVF curve
alignment, optionally allowing rotations and rescaling in addition to time
warping. Unlike tf_register(), this is a shape-registration interface: the
aligned curves live in centered shape space and the result stores rotations
and scale factors.
tf_register_shape( x, ..., template = NULL, max_iter = 3L, tol = 0.01, rotation = TRUE, scale = TRUE, mode = c("O", "C"), lambda = 0, store_x = TRUE )tf_register_shape( x, ..., template = NULL, max_iter = 3L, tol = 0.01, rotation = TRUE, scale = TRUE, mode = c("O", "C"), lambda = 0, store_x = TRUE )
x |
a regular shared-grid |
... |
additional arguments passed to fdasrvf alignment routines, such as
|
template |
optional length-one |
max_iter |
integer: maximum template refinement iterations when
|
tol |
numeric: relative template convergence tolerance. |
rotation |
logical: allow rotations? Default |
scale |
logical: allow scale changes? Default |
mode |
character: curve mode for fdasrvf. Only open curves ( |
lambda |
numeric: non-negative elastic penalty passed to the fdasrvf
alignment routines. Larger values penalise warping. Default |
store_x |
logical: store original data in the result object? |
When scale = TRUE the aligned curves returned by tf_aligned() are
renormalised to a common (mean) arc length so that congruent shapes overlay.
The per-curve factors returned by tf_scales() are the sizes that were
removed: multiplying an aligned curve by its scale factor rescales it back to
the corresponding input curve's arc length, so a value > 1 means the input
curve was larger than the shared aligned size and < 1 means it was smaller.
With scale = FALSE warping and rotation preserve arc length, so all factors
are 1. With template = NULL the returned tf_template() is the empirical
mean of the aligned shape-space curves rather than any single input curve.
Only open curves (mode = "O") are supported. Closed curves (mode = "C")
additionally optimise over a circular seed shift that the returned warping
functions do not represent, which would make the stored warps inconsistent
with the aligned curves; mode = "C" is therefore rejected for now.
A tf_shape_registration object. Access aligned curves with
tf_aligned(), inverse warps with tf_inv_warps(), the template with
tf_template(), rotations with tf_rotations(), and scales with
tf_scales().
Other registration functions:
tf_align(),
tf_estimate_warps(),
tf_landmarks_extrema(),
tf_register(),
tf_registration,
tf_warp()
t <- seq(0, 1, length.out = 51) base <- rbind(t, t^2) beta <- array(NA_real_, dim = c(3, length(t), 2)) for (i in 1:3) { beta[i,, 1] <- base[1, ] beta[i,, 2] <- base[2, ] } curves <- tfd_mv(beta, arg = t) reg <- tf_register_shape(curves, max_iter = 1) tf_rotations(reg) tf_scales(reg)t <- seq(0, 1, length.out = 51) base <- rbind(t, t^2) beta <- array(NA_real_, dim = c(3, length(t), 2)) for (i in 1:3) { beta[i,, 1] <- base[1, ] beta[i,, 2] <- base[2, ] } curves <- tfd_mv(beta, arg = t) reg <- tf_register_shape(curves, max_iter = 1) tf_rotations(reg) tf_scales(reg)
tf_registration objects store the result of tf_register(), including
the aligned (registered) curves, estimated inverse warping functions
(observed aligned time), and the template used.
Use accessors tf_aligned(), tf_inv_warps(), and tf_template() to extract
components.
tf_shape_registration objects, returned by tf_register_shape(), extend
this structure with shape-space rotations and scale factors. Use
tf_rotations() and tf_scales() to extract those components.
tf_aligned(x) tf_inv_warps(x) tf_template(x) tf_rotations(x) tf_scales(x) ## S3 method for class 'tf_registration' print(x, ...) ## S3 method for class 'tf_shape_registration' print(x, ...) ## S3 method for class 'tf_registration' summary(object, ...) ## S3 method for class 'summary.tf_registration' print(x, ...) ## S3 method for class 'tf_shape_registration' summary(object, ...) ## S3 method for class 'summary.tf_shape_registration' print(x, ...) ## S3 method for class 'tf_registration' plot(x, ...) ## S3 method for class 'tf_registration' x[i] ## S3 method for class 'tf_registration' length(x) ## S3 method for class 'tf_shape_registration' x[i]tf_aligned(x) tf_inv_warps(x) tf_template(x) tf_rotations(x) tf_scales(x) ## S3 method for class 'tf_registration' print(x, ...) ## S3 method for class 'tf_shape_registration' print(x, ...) ## S3 method for class 'tf_registration' summary(object, ...) ## S3 method for class 'summary.tf_registration' print(x, ...) ## S3 method for class 'tf_shape_registration' summary(object, ...) ## S3 method for class 'summary.tf_shape_registration' print(x, ...) ## S3 method for class 'tf_registration' plot(x, ...) ## S3 method for class 'tf_registration' x[i] ## S3 method for class 'tf_registration' length(x) ## S3 method for class 'tf_shape_registration' x[i]
x |
a |
... |
additional arguments (currently unused) |
object |
a |
i |
index for subsetting (integer, logical, or character) |
For tf_registration objects: a list with entries registered
(tf-vector of aligned/registered functions from x), inv_warps
(inverse warping functions aligning x to the template function), the
template function, the original data x (if store_x = TRUE was used
in tf_register()), and the call to tf_register() that created the
object. tf_shape_registration objects additionally contain the forward
warps, rotations, and scales. Accessors return the respective
component.
summary() computes per-curve diagnostics for assessing registration
quality and prints their averages and/or deciles.
The printed output contains four sections:
Amplitude variance reduction (only if store_x = TRUE): the proportion
of pointwise variance removed by registration, computed as
where is the mean (across the domain) of the pointwise
variance (across curves). Values near 1 indicate that registration
removed most of the original variability; values near 0 indicate little
change; negative values indicate that registration increased variability
(a sign that something went wrong).
Warp deviation from identity (deciles across curves): each curve's
inverse warping function is compared to the identity via the
normalized integral , where is the domain
length. The normalizing constant is the theoretical upper limit
deviation for a monotone, domain-preserving warp that maps all timepoints to
the first or last timepoint, so values range from 0 (identity warp, no time
deformation) to 1 (maximal crazy warping). Values above may
suggest aggressive warping that could warrant inspection.
Warp slopes (deciles of per-curve min and max ): a slope of 1
of the warp corresponds to no local time deformation (identity).
Slopes indicate local time dilation (the warped curve is
"stretched" relative to the template), slopes indicate local time
compression, so slopes near 0 or very large slopes indicate extreme local
deformation. For affine shift warps, all slopes are exactly 1.
Domain coverage loss (only printed if any loss occurs): the fraction of
the original domain range that is lost per curve after alignment, computed
as 1 - range(aligned_arg) / range(original_arg). This is only relevant
for affine (non-domain-preserving) warps where alignment can shift parts of
curves outside the original domain. Domain-preserving methods (srvf,
cc, landmark) always have zero domain loss.
tf_aligned(x): extract the registered/aligned curves (tfd vector).
tf_inv_warps(x): extract the estimated inverse warping functions
that map observed time to aligned time (tfd vector).
Use tf_invert() on the result to obtain forward warps if needed.
tf_template(x): extract the template function (tf vector of length 1).
tf_rotations(x): extract the per-curve rotation matrices from a
tf_shape_registration object.
tf_scales(x): extract the per-curve scale factors from a
tf_shape_registration object. Each factor is relative to the template
(template SRVF norm divided by the curve's SRVF norm); see
tf_register_shape().
Fabian Scheipl, Claude Opus 4.6
Other registration functions:
tf_align(),
tf_estimate_warps(),
tf_landmarks_extrema(),
tf_register(),
tf_register_shape(),
tf_warp()
reg <- tf_register(pinch[1:5], method = "affine", type = "shift_scale") reg summary(reg) plot(reg)reg <- tf_register(pinch[1:5], method = "affine", type = "shift_scale") reg summary(reg) plot(reg)
Generates n realizations of a zero-mean Gaussian process. The function also
accepts user-defined covariance functions (without "nugget" effect, see
cov), The implemented defaults with scale parameter , order
and nugget effect variance are:
squared exponential: .
Wiener process: ,
Brownian Bridge process for
:
tf_rgp( n, arg = 51L, cov = c("squareexp", "wiener", "matern", "brown_bridge"), scale = diff(domain)/10, nugget = scale/200, order = 1.5, domain = NULL )tf_rgp( n, arg = 51L, cov = c("squareexp", "wiener", "matern", "brown_bridge"), scale = diff(domain)/10, nugget = scale/200, order = 1.5, domain = NULL )
n |
how many realizations to draw. |
arg |
vector of evaluation points ( |
cov |
type of covariance function to use. Implemented defaults are
|
scale |
scale parameter (see description). Defaults to the width of the domain divided by 10. |
nugget |
nugget effect for additional white noise / unstructured
variability. Defaults to |
order |
order of the Matérn covariance (if used, must be >0), defaults
to 1.5. The higher, the smoother the process. Evaluation of the covariance
function becomes numerically unstable for large (>20) |
domain |
of the generated functions. If not provided, the range of the
supplied |
an tfd-vector of length n.
Other tidyfun RNG functions:
tf_jiggle()
(x1 <- tf_rgp(10, cov = "squareexp", nugget = 0)) tf_rgp(2, arg = list(sort(runif(25)), sort(runif(34))))(x1 <- tf_rgp(10, cov = "squareexp", nugget = 0)) tf_rgp(2, arg = list(sort(runif(25)), sort(runif(34))))
tf objectsApply running means or medians, lowess or Savitzky-Golay
filtering to smooth functional data. This does nothing for tfb-objects,
which should be smoothed by using a smaller basis / stronger penalty.
tf_smooth(x, ...) ## S3 method for class 'tfb' tf_smooth(x, verbose = TRUE, ...) ## S3 method for class 'tfd' tf_smooth( x, method = c("lowess", "rollmean", "rollmedian", "savgol"), verbose = TRUE, ... )tf_smooth(x, ...) ## S3 method for class 'tfb' tf_smooth(x, verbose = TRUE, ...) ## S3 method for class 'tfd' tf_smooth( x, method = c("lowess", "rollmean", "rollmedian", "savgol"), verbose = TRUE, ... )
x |
a |
... |
arguments for the respective |
verbose |
give lots of diagnostic messages? Defaults to |
method |
one of |
tf_smooth.tfd overrides/automatically sets some defaults of the
used methods:
lowess uses a span parameter of f = 0.15 (instead of 0.75)
by default.
rollmean/median use a window size of k = $<$number of
grid points$>$/20 (i.e., the nearest odd integer to that) and sets fill= "extend" (i.e., constant extrapolation to replace missing values at the
extremes of the domain) by default. Use fill= NA for zoo's default
behavior of shortening the smoothed series.
savgol uses a window size of k = $<$number of
grid points$>$/10 (i.e., the nearest odd integer to that).
a smoothed version of the input. For some methods/options, the smoothed functions may be shorter than the original ones (at both ends).
library(zoo) f <- tf_sparsify(tf_jiggle(tf_rgp(4, 201, nugget = 0.05))) f_lowess <- tf_smooth(f, "lowess") # these methods ignore the distances between arg-values: f_mean <- tf_smooth(f, "rollmean") f_median <- tf_smooth(f, "rollmedian", k = 31) f_sg <- tf_smooth(f, "savgol", fl = 31) layout(t(1:4)) plot(f, points = FALSE, main = "original") plot(f_lowess, points = FALSE, col = "blue", main = "lowess (default,\n span 0.9 in red)" ) lines(tf_smooth(f, "lowess", f = 0.9), col = "red", alpha = 0.2) plot(f_mean, points = FALSE, col = "blue", main = "rolling means &\n medians (red)" ) lines(f_median, col = "red", alpha = 0.2) # note constant extrapolation at both ends! plot(f, points = FALSE, main = "original and\n savgol (red)") lines(f_sg, col = "red")library(zoo) f <- tf_sparsify(tf_jiggle(tf_rgp(4, 201, nugget = 0.05))) f_lowess <- tf_smooth(f, "lowess") # these methods ignore the distances between arg-values: f_mean <- tf_smooth(f, "rollmean") f_median <- tf_smooth(f, "rollmedian", k = 31) f_sg <- tf_smooth(f, "savgol", fl = 31) layout(t(1:4)) plot(f, points = FALSE, main = "original") plot(f_lowess, points = FALSE, col = "blue", main = "lowess (default,\n span 0.9 in red)" ) lines(tf_smooth(f, "lowess", f = 0.9), col = "red", alpha = 0.2) plot(f_mean, points = FALSE, col = "blue", main = "rolling means &\n medians (red)" ) lines(f_median, col = "red", alpha = 0.2) # note constant extrapolation at both ends! plot(f, points = FALSE, main = "original and\n savgol (red)") lines(f_sg, col = "red")
tf_split separates each function into a vector of functions defined on a sub-interval of
its domain, either with overlap at the cut points or without.
tf_combine joins functional fragments together to create longer (or more densely evaluated) functions.
tf_split(x, splits, include = c("both", "left", "right")) tf_combine(..., strict = FALSE)tf_split(x, splits, include = c("both", "left", "right")) tf_combine(..., strict = FALSE)
x |
a |
splits |
numeric vector containing |
include |
which of the end points defined by |
... |
|
strict |
only combine functions whose argument ranges do not overlap,
are given in the correct order & contain no duplicate values at identical arguments?
defaults to |
for tf_split: a list of tf objects.
for tf_combine: a tfd with the combined subfunctions on the union of the input tf_arg-values
x <- tfd(1:100, arg = 1:100) tf_split(x, splits = c(20, 80)) tf_split(x, splits = c(20, 80), include = "left") tf_split(x, splits = c(20, 80), include = "right") x <- tf_rgp(5) tfs <- tf_split(x, splits = c(.2, .6)) x2 <- tf_combine(tfs[[1]], tfs[[2]], tfs[[3]]) # tf_combine(tfs[[1]], tfs[[2]], tfs[[3]], strict = TRUE) # errors out - duplicate values! all.equal(x, x2) # combine works for different input types: tfs2_sparse <- tf_sparsify(tfs[[2]]) tfs3_spline <- tfb(tfs[[3]]) tf_combine(tfs[[1]], tfs2_sparse, tfs3_spline) # combine(.., strict = FALSE) can be used to coalesce different measurements # of the same process over different grids: x1 <- tfd(x, arg = tf_arg(x)[seq(1, 51, by = 2)]) x2 <- tfd(x, arg = tf_arg(x)[seq(2, 50, by = 2)]) tf_combine(x2, x1, strict = FALSE) == x plot(tf_combine(x2, x1, strict = FALSE)) points(x1, col = "blue", pch = "x") points(x2, col = "red", pch = "o")x <- tfd(1:100, arg = 1:100) tf_split(x, splits = c(20, 80)) tf_split(x, splits = c(20, 80), include = "left") tf_split(x, splits = c(20, 80), include = "right") x <- tf_rgp(5) tfs <- tf_split(x, splits = c(.2, .6)) x2 <- tf_combine(tfs[[1]], tfs[[2]], tfs[[3]]) # tf_combine(tfs[[1]], tfs[[2]], tfs[[3]], strict = TRUE) # errors out - duplicate values! all.equal(x, x2) # combine works for different input types: tfs2_sparse <- tf_sparsify(tfs[[2]]) tfs3_spline <- tfb(tfs[[3]]) tf_combine(tfs[[1]], tfs2_sparse, tfs3_spline) # combine(.., strict = FALSE) can be used to coalesce different measurements # of the same process over different grids: x1 <- tfd(x, arg = tf_arg(x)[seq(1, 51, by = 2)]) x2 <- tfd(x, arg = tf_arg(x)[seq(2, 50, by = 2)]) tf_combine(x2, x1, strict = FALSE) == x plot(tf_combine(x2, x1, strict = FALSE)) points(x1, col = "blue", pch = "x") points(x2, col = "red", pch = "o")
tf vectorsThese functions stretch and/or compress regions of the domain of functional data:
tf_warp() applies warping functions to aligned (registered) functional data
to recover the original unregistered curves: .
tf_align() applies the inverse warping function to unregistered data
to obtain aligned (registered) functions: .
tf_warp(x, warp, ...) ## S3 method for class 'tfd' tf_warp(x, warp, ..., keep_new_arg = FALSE) ## S3 method for class 'tfb' tf_warp(x, warp, ...)tf_warp(x, warp, ...) ## S3 method for class 'tfd' tf_warp(x, warp, ..., keep_new_arg = FALSE) ## S3 method for class 'tfb' tf_warp(x, warp, ...)
x |
|
warp |
|
... |
additional arguments passed to |
keep_new_arg |
keep new |
These functions will work best with functions evaluated on suitably dense and regular grids.
Warping functions are strictly monotone increasing (no time
travel backwards or infinite time dilation) with identical domain and
co-domain: . Their input is the aligned "system" time ,
their output is the unaligned "observed" time .
By default (keep_new_arg = FALSE), the tfd methods will return function objects
re-evaluated on the same grids as the original inputs,
which will typically incur some additional interpolation error because (un)warping
changes the underlying grids, which are then changed back. Set to TRUE to avoid.
This option is not available for tfb-objects.
tf_warp(): the warped tf vector (un-registered functions)
tf_align(): the aligned tf vector (registered functions)
Maximilian Muecke, Fabian Scheipl, Claude Opus 4.6
Other registration functions:
tf_align(),
tf_estimate_warps(),
tf_landmarks_extrema(),
tf_register(),
tf_register_shape(),
tf_registration
# generate "template" function shape on [0, 1]: set.seed(1351) template <- tf_rgp(1, arg = 201L, nugget = 0) # generate random warping functions (strictly monotone inc., [0, 1] -> [0, 1]): warp <- { tmp <- tf_rgp(5) tmp <- exp(tmp - mean(tmp)) # centered at identity warping tf_integrate(tmp, definite = FALSE) / tf_integrate(tmp) } x <- tf_warp(rep(1, 5) * template, warp) layout(t(1:3)) plot(template); plot(warp, col = 1:5); plot(x, col = 1:5) # register the functions: if (requireNamespace("fdasrvf", quietly = TRUE)) { reg <- tf_register(x) } else { reg <- tf_register(x, method = "affine", type = "shift_scale") } layout(t(1:3)) plot(x, col = 1:5) plot(tf_inv_warps(reg), col = 1:5); lines(tf_invert(warp), lty = 3, lwd = 1.5, col = 1:5) plot(tf_aligned(reg), col = 1:5, points = FALSE); lines(template, lty = 2)# generate "template" function shape on [0, 1]: set.seed(1351) template <- tf_rgp(1, arg = 201L, nugget = 0) # generate random warping functions (strictly monotone inc., [0, 1] -> [0, 1]): warp <- { tmp <- tf_rgp(5) tmp <- exp(tmp - mean(tmp)) # centered at identity warping tf_integrate(tmp, definite = FALSE) / tf_integrate(tmp) } x <- tf_warp(rep(1, 5) * template, warp) layout(t(1:3)) plot(template); plot(warp, col = 1:5); plot(x, col = 1:5) # register the functions: if (requireNamespace("fdasrvf", quietly = TRUE)) { reg <- tf_register(x) } else { reg <- tf_register(x, method = "affine", type = "shift_scale") } layout(t(1:3)) plot(x, col = 1:5) plot(tf_inv_warps(reg), col = 1:5); lines(tf_invert(warp), lty = 3, lwd = 1.5, col = 1:5) plot(tf_aligned(reg), col = 1:5, points = FALSE); lines(template, lty = 2)
tf_where allows to define a logical expression about the function values
and returns the argument values for which that condition is true.tf_anywhere is syntactic sugar for tf_where with return = "any" to
get a logical flag for each function if the condition is TRUE anywhere,
see below.
tf_where( f, cond, return = c("all", "first", "last", "range", "any"), arg = tf_arg(f) ) tf_anywhere(f, cond, arg = tf_arg(f))tf_where( f, cond, return = c("all", "first", "last", "range", "any"), arg = tf_arg(f) ) tf_anywhere(f, cond, arg = tf_arg(f))
f |
a |
cond |
a logical expression about |
return |
for each entry in |
arg |
optional |
Entries in f that do not fulfill cond anywhere yield numeric(0).cond is evaluated as a base::subset()-statement on a data.frame
containing a single entry in f with columns arg and value, so most
of the usual dplyr tricks are available as well, see examples.
Any condition evaluates to NA on NA-entries in f.
For vector-valued (tf_mv) input, the data.frame on which cond is
evaluated has one column per component, named like the components, instead
of a single value column: conditions are joint conditions across
components, e.g. tf_where(f, x > 0 & y < 1) or
tf_where(f, sqrt(x^2 + y^2) > 1) for components "x" and "y". To apply
a condition to a single component, extract it first:
tf_where(f[, component = "x"], value > 0). All components have to be
observed on a common grid – use tf_interpolate() to align them first, or
supply arg explicitly.
depends on return:
return = "any", i.e, anywhere:
a logical vector of the same length as f.
return = "all": a list of vectors of the same length as f, with
empty vectors for the functions that never fulfill the condition.
return = "range": a data frame with columns "begin" and "end".
else, a numeric vector of the same length as f with NA for entries of
f that nowhere fulfill the condition.
lin <- 1:4 * tfd(seq(-1, 1, length.out = 11), seq(-1, 1, length.out = 11)) tf_where(lin, value %inr% c(-1, 0.5)) tf_where(lin, value %inr% c(-1, 0.5), "range") a <- 1 tf_where(lin, value > a, "first") tf_where(lin, value < a, "last") tf_where(lin, value > 2, "any") tf_anywhere(lin, value > 2) set.seed(4353) f <- tf_rgp(5, 11) plot(f, pch = as.character(1:5), points = TRUE) tf_where(f, value == max(value)) # where is the function increasing/decreasing? tf_where(f, value > dplyr::lag(value, 1, value[1])) tf_where(f, value < dplyr::lead(value, 1, tail(value, 1))) # where are the (interior) extreme points (sign changes of `diff(value)`)? tf_where( f, sign(c(diff(value)[1], diff(value))) != sign(c(diff(value), tail(diff(value), 1))) ) # where in its second half is the function positive? tf_where(f, arg > 0.5 & value > 0) # does the function ever exceed? tf_anywhere(f, value > 1) # vector-valued input: conditions refer to components by name fm <- tfd_mv(list(x = tf_rgp(3, 11L), y = tf_rgp(3, 11L))) tf_where(fm, x > 0 & y < 0) tf_where(fm, sqrt(x^2 + y^2) > 1, "first") tf_anywhere(fm, x > y)lin <- 1:4 * tfd(seq(-1, 1, length.out = 11), seq(-1, 1, length.out = 11)) tf_where(lin, value %inr% c(-1, 0.5)) tf_where(lin, value %inr% c(-1, 0.5), "range") a <- 1 tf_where(lin, value > a, "first") tf_where(lin, value < a, "last") tf_where(lin, value > 2, "any") tf_anywhere(lin, value > 2) set.seed(4353) f <- tf_rgp(5, 11) plot(f, pch = as.character(1:5), points = TRUE) tf_where(f, value == max(value)) # where is the function increasing/decreasing? tf_where(f, value > dplyr::lag(value, 1, value[1])) tf_where(f, value < dplyr::lead(value, 1, tail(value, 1))) # where are the (interior) extreme points (sign changes of `diff(value)`)? tf_where( f, sign(c(diff(value)[1], diff(value))) != sign(c(diff(value), tail(diff(value), 1))) ) # where in its second half is the function positive? tf_where(f, arg > 0.5 & value > 0) # does the function ever exceed? tf_anywhere(f, value > 1) # vector-valued input: conditions refer to components by name fm <- tfd_mv(list(x = tf_rgp(3, 11L), y = tf_rgp(3, 11L))) tf_where(fm, x > 0 & y < 0) tf_where(fm, sqrt(x^2 + y^2) > 1, "first") tf_anywhere(fm, x > y)
These are used to redefine or restrict the domain of tf objects.
tf_zoom(f, begin, end, ...) ## S3 method for class 'tfd' tf_zoom(f, begin = tf_domain(f)[1], end = tf_domain(f)[2], ...) ## S3 method for class 'tfb' tf_zoom(f, begin = tf_domain(f)[1], end = tf_domain(f)[2], ...) ## S3 method for class 'tfb_fpc' tf_zoom(f, begin = tf_domain(f)[1], end = tf_domain(f)[2], ...)tf_zoom(f, begin, end, ...) ## S3 method for class 'tfd' tf_zoom(f, begin = tf_domain(f)[1], end = tf_domain(f)[2], ...) ## S3 method for class 'tfb' tf_zoom(f, begin = tf_domain(f)[1], end = tf_domain(f)[2], ...) ## S3 method for class 'tfb_fpc' tf_zoom(f, begin = tf_domain(f)[1], end = tf_domain(f)[2], ...)
f |
a |
begin |
numeric vector of length 1 or |
end |
numeric vector of length 1 or |
... |
not used |
an object like f on a new domain (potentially).
Note that regular functional data and functions in basis representation will
be turned into irregular tfd-objects if begin or end are not scalar.
Other tidyfun utility functions:
ensure_list(),
in_range(),
tf_arg(),
unique_id()
x <- tf_rgp(10) plot(x) tf_zoom(x, 0.5, 0.9) tf_zoom(x, 0.5, 0.9) |> lines(col = "red") tf_zoom(x, seq(0, 0.5, length.out = 10), seq(0.5, 1, length.out = 10)) |> lines(col = "blue", lty = 3)x <- tf_rgp(10) plot(x) tf_zoom(x, 0.5, 0.9) tf_zoom(x, 0.5, 0.9) |> lines(col = "red") tf_zoom(x, seq(0, 0.5, length.out = 10), seq(0.5, 1, length.out = 10)) |> lines(col = "blue", lty = 3)
Various constructors for tfb-vectors from different kinds of inputs.
tfb(data = data_frame0(), basis = c("spline", "fpc", "wavelet"), ...) tfb_wavelet(data, ...) as.tfb(data, basis = c("spline", "fpc"), ...)tfb(data = data_frame0(), basis = c("spline", "fpc", "wavelet"), ...) tfb_wavelet(data, ...) as.tfb(data, basis = c("spline", "fpc"), ...)
data |
a |
basis |
either " |
... |
further arguments for |
tfb is a wrapper for functions that set up spline-, principal component- or
wavelet-based representations of functional data. For all three, the input
data are represented as weighted sums of a set of common basis
functions identical for all observations and
weight or coefficient vectors estimated
for each observation: . Depending on
the value of basis, the basis functions will either be spline
functions or the first few estimated eigenfunctions of the covariance
operator of the (fpc) or wavelets (wavelet).
See tfb_spline() for more details on spline basis representation (the
default). See tfb_fpc() for using an functional principal component
representation with an orthonormal basis estimated from the data instead.
a tfb-object (or a data.frame/matrix for the conversion
functions, obviously).
Other tfb-class:
fpc_wsvd(),
tfb_fpc(),
tfb_spline()
arg <- seq(0, 1, length.out = 21) x <- tfd(rbind(sin(2 * pi * arg), cos(2 * pi * arg)), arg = arg) xb <- tfb(x, k = 8, penalized = FALSE) xb as.tfb(x, basis = "spline", k = 8)arg <- seq(0, 1, length.out = 21) x <- tfd(rbind(sin(2 * pi * arg), cos(2 * pi * arg)), arg = arg) xb <- tfb(x, k = 8, penalized = FALSE) xb as.tfb(x, basis = "spline", k = 8)
These functions perform a (functional) principal component analysis (FPCA) of
the input data and return an tfb_fpc tf-object that uses the empirical
eigenfunctions as basis functions for representing the data. The default
("method = fpc_wsvd") uses a (truncated) weighted SVD for complete
data on a common grid and a nuclear-norm regularized (truncated) weighted SVD
for partially missing data on a common grid, see fpc_wsvd().
The latter is likely to break down for high PVE and/or high amounts of
missingness.
tfb_fpc(data, ...) ## S3 method for class 'data.frame' tfb_fpc( data, id = 1, arg = 2, value = 3, domain = NULL, method = fpc_wsvd, ... ) ## S3 method for class 'matrix' tfb_fpc(data, arg = NULL, domain = NULL, method = fpc_wsvd, ...) ## S3 method for class 'numeric' tfb_fpc(data, arg = NULL, domain = NULL, method = fpc_wsvd, ...) ## S3 method for class 'tf' tfb_fpc(data, arg = NULL, method = fpc_wsvd, ...) ## Default S3 method: tfb_fpc(data, arg = NULL, domain = NULL, method = fpc_wsvd, ...)tfb_fpc(data, ...) ## S3 method for class 'data.frame' tfb_fpc( data, id = 1, arg = 2, value = 3, domain = NULL, method = fpc_wsvd, ... ) ## S3 method for class 'matrix' tfb_fpc(data, arg = NULL, domain = NULL, method = fpc_wsvd, ...) ## S3 method for class 'numeric' tfb_fpc(data, arg = NULL, domain = NULL, method = fpc_wsvd, ...) ## S3 method for class 'tf' tfb_fpc(data, arg = NULL, method = fpc_wsvd, ...) ## Default S3 method: tfb_fpc(data, arg = NULL, domain = NULL, method = fpc_wsvd, ...)
data |
a |
... |
arguments to the |
id |
The name or number of the column defining which data belong to which function. |
arg |
For the |
value |
The name or number of the column containing the function evaluations. |
domain |
range of the |
method |
the function to use that computes eigenfunctions and scores.
Defaults to |
For the FPC basis, any factorization method that accepts a data.frame with
columns id, arg, value containing the functional data and returns a
list with eigenfunctions and FPC scores structured like the return object
of fpc_wsvd() can be used for the method argument, see example below.
Note that the mean function, with a fixed "score" of 1 for all functions,
is used as the first basis function for all FPC bases.
an object of class tfb_fpc, inheriting from tfb.
The basis used by tfb_fpc is a tfd-vector containing the estimated
mean and eigenfunctions.
tfb_fpc(default): convert tfb: default method, returning prototype when
data is NULL
fpc_wsvd() for FPCA options.
Other tfb-class:
fpc_wsvd(),
tfb(),
tfb_spline()
Other tfb_fpc-class:
fpc_wsvd(),
tfb_mfpc()
set.seed(13121) x <- tf_rgp(25, nugget = .02) x_pc <- tfb_fpc(x, pve = .9) x_pc plot(x, lwd = 3) lines(x_pc, col = 2, lty = 2) x_pc_full <- tfb_fpc(x, pve = .995) x_pc_full lines(x_pc_full, col = 3, lty = 2) # partially missing data on common grid: x_mis <- x |> tf_sparsify(dropout = .05) x_pc_mis <- tfb_fpc(x_mis, pve = .9) x_pc_mis plot(x_mis, lwd = 3) lines(x_pc_mis, col = 4, lty = 2) # extract FPC basis -- # first "eigenvector" in black is (always) the mean function x_pc |> tf_basis(as_tfd = TRUE) |> plot(col = 1:5) # Apply FPCA for sparse, irregular data using refund::fpca.sc: set.seed(99290) # create small, sparse, irregular data: x_irreg <- x[1:8] |> tf_jiggle() |> tf_sparsify(dropout = 0.3) plot(x_irreg) x_df <- x_irreg |> as.data.frame(unnest = TRUE) # wrap refund::fpca_sc for use as FPCA method in tfb_fpc -- # 1. define scoring function (simple weighted LS fit) fpca_scores <- function(data_matrix, efunctions, mean, weights) { w_mat <- matrix(weights, ncol = length(weights), nrow = nrow(data_matrix), byrow = TRUE) w_mat[is.na(data_matrix)] <- 0 data_matrix[is.na(data_matrix)] <- 0 data_wc <- t((t(data_matrix) - mean) * sqrt(t(w_mat))) t(qr.coef(qr(efunctions), t(data_wc) / sqrt(weights))) } # 2. define wrapper for fpca_sc: fpca_sc_wrapper <- function(data, arg, pve = 0.995, ...) { data_mat <- tfd(data) |> as.matrix(interpolate = TRUE) fpca <- refund::fpca.sc( Y = data_mat, argvals = attr(data_mat, "arg"), pve = pve, ... ) c(fpca[c("mu", "efunctions", "scores", "npc")], scoring_function = fpca_scores) } x_pc <- tfb_fpc(x_df, method = fpca_sc_wrapper) lines(x_pc, col = 2, lty = 2)set.seed(13121) x <- tf_rgp(25, nugget = .02) x_pc <- tfb_fpc(x, pve = .9) x_pc plot(x, lwd = 3) lines(x_pc, col = 2, lty = 2) x_pc_full <- tfb_fpc(x, pve = .995) x_pc_full lines(x_pc_full, col = 3, lty = 2) # partially missing data on common grid: x_mis <- x |> tf_sparsify(dropout = .05) x_pc_mis <- tfb_fpc(x_mis, pve = .9) x_pc_mis plot(x_mis, lwd = 3) lines(x_pc_mis, col = 4, lty = 2) # extract FPC basis -- # first "eigenvector" in black is (always) the mean function x_pc |> tf_basis(as_tfd = TRUE) |> plot(col = 1:5) # Apply FPCA for sparse, irregular data using refund::fpca.sc: set.seed(99290) # create small, sparse, irregular data: x_irreg <- x[1:8] |> tf_jiggle() |> tf_sparsify(dropout = 0.3) plot(x_irreg) x_df <- x_irreg |> as.data.frame(unnest = TRUE) # wrap refund::fpca_sc for use as FPCA method in tfb_fpc -- # 1. define scoring function (simple weighted LS fit) fpca_scores <- function(data_matrix, efunctions, mean, weights) { w_mat <- matrix(weights, ncol = length(weights), nrow = nrow(data_matrix), byrow = TRUE) w_mat[is.na(data_matrix)] <- 0 data_matrix[is.na(data_matrix)] <- 0 data_wc <- t((t(data_matrix) - mean) * sqrt(t(w_mat))) t(qr.coef(qr(efunctions), t(data_wc) / sqrt(weights))) } # 2. define wrapper for fpca_sc: fpca_sc_wrapper <- function(data, arg, pve = 0.995, ...) { data_mat <- tfd(data) |> as.matrix(interpolate = TRUE) fpca <- refund::fpca.sc( Y = data_mat, argvals = attr(data_mat, "arg"), pve = pve, ... ) c(fpca[c("mu", "efunctions", "scores", "npc")], scoring_function = fpca_scores) } x_pc <- tfb_fpc(x_df, method = fpca_sc_wrapper) lines(x_pc, col = 2, lty = 2)
f: R -> R^d)tfb_mfpc() computes a multivariate functional principal component
analysis (MFPCA) of vector-valued functional data in the sense of
Happ & Greven (2018): a single set of scalar scores per curve, shared across
all d components, together with vector-valued eigenfunctions
, so that
.
tfb_mfpc(data, ...) ## S3 method for class 'tf_mv' tfb_mfpc( data, weights = c("inverse_variance", "snr", "equal"), pve = 0.995, npc = NULL, uni_pve = 0.995, method = fpc_wsvd, ... ) ## S3 method for class 'list' tfb_mfpc(data, arg = NULL, domain = NULL, ...) ## Default S3 method: tfb_mfpc(data, arg = NULL, domain = NULL, ...) is_tfb_mfpc(x) tf_mfpc_scores(x) tf_mfpc_efunctions(x)tfb_mfpc(data, ...) ## S3 method for class 'tf_mv' tfb_mfpc( data, weights = c("inverse_variance", "snr", "equal"), pve = 0.995, npc = NULL, uni_pve = 0.995, method = fpc_wsvd, ... ) ## S3 method for class 'list' tfb_mfpc(data, arg = NULL, domain = NULL, ...) ## Default S3 method: tfb_mfpc(data, arg = NULL, domain = NULL, ...) is_tfb_mfpc(x) tf_mfpc_scores(x) tf_mfpc_efunctions(x)
data |
a |
... |
further arguments forwarded to the univariate |
weights |
component weighting scheme for the joint analysis. Either a
string – |
pve |
proportion of variance explained used to truncate the
multivariate components (default |
npc |
number of multivariate FPCs to retain (overrides |
uni_pve |
proportion of variance explained for the univariate FPCA of
each component (default |
method |
univariate FPCA method, see |
arg |
evaluation grid for raw (list/matrix/array) inputs, forwarded to
|
domain |
range of |
x |
a |
This is qualitatively different from tfb_mv(data, basis = "fpc"), which
fits an independent FPCA per component (separate eigenfunctions and
separate scores) and so cannot capture joint variation across dimensions.
The estimator first runs the univariate FPCA (see tfb_fpc() / fpc_wsvd())
on each component to obtain univariate scores and
eigenfunctions , then eigendecomposes the joint covariance of
the (weighted) stacked scores. With component weights the
shared scores and multivariate eigenfunctions are
where are the eigenvectors of the weighted joint score covariance.
The returned object is a tfb_mv() whose components are tfb_fpc() objects
sharing identical per-curve scores; cast it back to evaluations with
as.tfd_mv() / vec_cast(), and project new tfd_mv data onto the
fitted basis with tf_rebase(). Like the univariate FPCA, the estimator
targets data observed on a common grid per component; re-scoring new data
evaluates it on each component's estimation grid, so new curves must be
observable there.
a tfb_mv object whose d components are tfb_fpc() objects with
shared per-curve scores; is_tfb_mfpc() is TRUE for it. Use
tf_mfpc_scores() and tf_mfpc_efunctions() to extract the shared scores
and the multivariate eigenfunctions.
is_tfb_mfpc(): a logical flag.
tf_mfpc_scores(): an n x M matrix of shared multivariate FPC
scores (rows = curves, columns = components).
tf_mfpc_efunctions(): a tfd_mv of length M holding the
multivariate eigenfunctions (one "curve" per component).
Happ, Clara, Greven, Sonja (2018). “Multivariate functional principal component analysis for data observed on different (dimensional) domains.” Journal of the American Statistical Association, 113(522), 649–659.
tfb_mv() for independent per-component FPCA, tfb_fpc() /
fpc_wsvd() for the univariate machinery.
Other tf_mv-class:
plot.tf_mv(),
tf_arclength(),
tf_geom,
tf_mv_methods,
tfb_mv(),
tfd_mv()
Other tfb_fpc-class:
fpc_wsvd(),
tfb_fpc()
set.seed(1) g <- tfd_mv(list(hip = tf_rgp(20), knee = tf_rgp(20))) m <- tfb_mfpc(g, pve = 0.99) m dim(tf_mfpc_scores(m)) tf_mfpc_efunctions(m) # reconstruct and project new data: plot(as.tfd_mv(m), type = "facet") g_new <- tfd_mv(list(hip = tf_rgp(3), knee = tf_rgp(3))) tf_rebase(g_new, m)set.seed(1) g <- tfd_mv(list(hip = tf_rgp(20), knee = tf_rgp(20))) m <- tfb_mfpc(g, pve = 0.99) m dim(tf_mfpc_scores(m)) tf_mfpc_efunctions(m) # reconstruct and project new data: plot(as.tfd_mv(m), type = "facet") g_new <- tfd_mv(list(hip = tf_rgp(3), knee = tf_rgp(3))) tf_rebase(g_new, m)
f: R -> R^d)tfb_mv is the basis-representation analogue of tfd_mv(): it bundles d
univariate tfb() vectors (one per output dimension / component) into a
single vctrs vector of vector-valued functions . Each component is fitted independently with the usual
univariate tfb() machinery (spline or FPC basis), so all of its arguments
(k, bs, penalized, basis, ...) apply per component.
tfb_mv(data, ...) ## S3 method for class 'tf_mv' tfb_mv(data, basis = c("spline", "fpc"), ...) ## S3 method for class 'list' tfb_mv(data, basis = c("spline", "fpc"), arg = NULL, domain = NULL, ...) ## Default S3 method: tfb_mv(data, basis = c("spline", "fpc"), arg = NULL, domain = NULL, ...) as.tfb_mv(data, ...) ## Default S3 method: as.tfb_mv(data, ...)tfb_mv(data, ...) ## S3 method for class 'tf_mv' tfb_mv(data, basis = c("spline", "fpc"), ...) ## S3 method for class 'list' tfb_mv(data, basis = c("spline", "fpc"), arg = NULL, domain = NULL, ...) ## Default S3 method: tfb_mv(data, basis = c("spline", "fpc"), arg = NULL, domain = NULL, ...) as.tfb_mv(data, ...) ## Default S3 method: as.tfb_mv(data, ...)
data |
a |
... |
forwarded to the univariate |
basis |
spline (default) or fpc basis, see |
arg |
evaluation grid for raw (list/matrix/array) inputs, forwarded to
|
domain |
range of |
By default a single ... is shared across all components (every component
gets the same k, bs, sp, etc.). To pass different basis arguments
to different components, give the argument as a list named by component
names – e.g. tfb_mv(f, k = list(x = 5, y = 12)) fits component x with
k = 5 and component y with k = 12. Any list-valued ... whose names
do not match the component names is treated as a shared argument value.
(Already-tfb components passed via tfb_mv.list() are kept as-is, which
is the most permissive way to mix entirely different basis kinds across
components.)
a tfb_mv object.
Other tf_mv-class:
plot.tf_mv(),
tf_arclength(),
tf_geom,
tf_mv_methods,
tfb_mfpc(),
tfd_mv()
traj <- tfd_mv(list(x = tf_rgp(5), y = tf_rgp(5))) tb <- tfb_mv(traj, k = 7, verbose = FALSE) tb tf_ncomp(tb)traj <- tfd_mv(list(x = tf_rgp(5), y = tf_rgp(5))) tb <- tfb_mv(traj, k = 7, verbose = FALSE) tb tf_ncomp(tb)
Represent curves as a weighted sum of spline basis functions.
tfb_spline(data, ...) ## S3 method for class 'data.frame' tfb_spline( data, id = 1, arg = 2, value = 3, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'matrix' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'numeric' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'list' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'fd' tfb_spline( data, arg = NULL, domain = NULL, penalized = FALSE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'fdSmooth' tfb_spline( data, arg = NULL, domain = NULL, penalized = FALSE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'tfd' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'tfb' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## Default S3 method: tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... )tfb_spline(data, ...) ## S3 method for class 'data.frame' tfb_spline( data, id = 1, arg = 2, value = 3, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'matrix' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'numeric' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'list' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'fd' tfb_spline( data, arg = NULL, domain = NULL, penalized = FALSE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'fdSmooth' tfb_spline( data, arg = NULL, domain = NULL, penalized = FALSE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'tfd' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## S3 method for class 'tfb' tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... ) ## Default S3 method: tfb_spline( data, arg = NULL, domain = NULL, penalized = TRUE, global = FALSE, verbose = TRUE, ... )
data |
a |
... |
arguments to the calls to |
id |
The name or number of the column defining which data belong to which function. |
arg |
For the |
value |
The name or number of the column containing the function evaluations. |
domain |
range of the |
penalized |
|
global |
Defaults to |
verbose |
|
The basis to be used is set up via a call to mgcv::s() and all the spline
bases discussed in mgcv::smooth.terms() are available, in principle.
Depending on the value of the penalized- and global-flags, the
coefficient vectors for each observation are then estimated via fitting a GAM
(separately for each observation, if !global) via mgcv::magic() (least
square error, the default) or mgcv::gam() (if a family argument was
supplied) or unpenalized least squares / maximum likelihood.
After the "smoothed" representation is computed, the amount of smoothing that
was performed is reported in terms of the "percentage of variability
preserved", which is the variance (or the explained deviance, in the general
case if family was specified) of the smoothed function values divided by the variance of the original
values (the null deviance, in the general case). Reporting can be switched off
with verbose = FALSE.
The ... arguments supplies arguments to both the
spline basis (via mgcv::s()) and the estimation (via
mgcv::magic() or mgcv::gam()), the most important arguments are:
k: how many basis functions should the spline basis use, default is 25.
bs: which type of spline basis should be used, the default is cubic
regression splines (bs = "cr")
family argument: use this if minimizing squared errors is not
a reasonable criterion for the representation accuracy (see
mgcv::family.mgcv() for what's available) and/or if function values are
restricted to be e.g. positive (family = Gamma()/tw()/...), in
(family = betar()), etc.
sp: numeric value for the smoothness penalty weight, for manually
setting the amount of smoothing for all curves, see mgcv::s(). This
(drastically) reduces computation time. Defaults to -1, i.e., automatic
optimization of sp using mgcv::magic() (LS fits) or mgcv::gam() (GLM),
source code in R/tfb-spline-utils.R.
If global == TRUE, this uses a small subset of curves (10% of curves,
at least 5, at most 100; non-random sample using every j-th curve in the
data) on which smoothing parameters per curve are estimated and then takes
the mean of the log smoothing parameter of those as sp for all curves. This
is much faster than optimizing for each curve on large data sets. For very
sparse or noisy curves, estimating a common smoothing parameter based on the
data for all curves simultaneously is likely to yield better results, this is
not what's implemented here.
a tfb-object
tfb_spline(data.frame): convert data frames
tfb_spline(matrix): convert matrices
tfb_spline(numeric): convert matrices
tfb_spline(list): convert lists
tfb_spline(fd): convert fd objects. Almost exact re-representation for
objects using Fourier- or B-spline bases, other fda-style bases are not implemented here.
tfb_spline(fdSmooth): convert fdSmooth objects. Almost exact re-representation for
objects using Fourier- or B-spline bases, other fda-style bases are not implemented here.
tfb_spline(tfd): convert tfd (raw functional data)
tfb_spline(tfb): convert tfb: modify basis representation, smoothing.
tfb_spline(default): convert tfb: default method, returning prototype
when data is missing
mgcv::smooth.terms() for spline basis options.
Other tfb-class:
fpc_wsvd(),
tfb(),
tfb_fpc()
arg <- seq(0, 1, length.out = 21) mat <- rbind(sin(2 * pi * arg), cos(2 * pi * arg)) fit <- tfb_spline(mat, arg = arg, k = 8, penalized = FALSE, verbose = FALSE) fitarg <- seq(0, 1, length.out = 21) mat <- rbind(sin(2 * pi * arg), cos(2 * pi * arg)) fit <- tfb_spline(mat, arg = arg, k = 8, penalized = FALSE, verbose = FALSE) fit
Various constructor methods for tfd-objects.tfd objects contain vectors of function evaluations at observed arg-values,
either all at the same arg-values (tfd_reg) or at different arg-values (tfd_irreg).
NA-functions are represented by NULL-entries in that list.
tfd.matrix accepts a numeric matrix with one function per
row (!). If arg is not provided, it tries to guess arg from the
column names and falls back on 1:ncol(data) if that fails.
tfd.data.frame uses the first 3 columns of data for
id (function ID), arg (argument value) and value (function value)
by default.
tfd.list accepts a list of vectors of identical lengths
containing evaluations or a list of 2-column matrices/data.frames with
arg in the first and evaluations in the second column
tfd.default returns class prototype when argument to tfd() is
NULL or not a recognised class.
as.tfd_irreg converts regular tfd or tfb objects into
irregular ones. Mainly used internally for tf_rebase operations etc.
tfd(data, ...) ## S3 method for class 'matrix' tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'numeric' tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'data.frame' tfd( data, id = 1, arg = 2, value = 3, domain = NULL, evaluator = tf_approx_linear, ... ) ## S3 method for class 'list' tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'tf' tfd(data, arg = NULL, domain = NULL, evaluator = NULL, ...) ## Default S3 method: tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) as.tfd(data, ...) as.tfd_irreg(data, ...)tfd(data, ...) ## S3 method for class 'matrix' tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'numeric' tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'data.frame' tfd( data, id = 1, arg = 2, value = 3, domain = NULL, evaluator = tf_approx_linear, ... ) ## S3 method for class 'list' tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'tf' tfd(data, arg = NULL, domain = NULL, evaluator = NULL, ...) ## Default S3 method: tfd(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) as.tfd(data, ...) as.tfd_irreg(data, ...)
data |
a |
... |
not used in |
arg |
For the |
domain |
range of the |
evaluator |
a function accepting arguments |
id |
The name or number of the column defining which data belong to which function. |
value |
The name or number of the column containing the function evaluations. |
tfd-objects are list-vctrs of numeric vectors containing function
evaluations.
evaluator: must be the (quoted or bare) name of a
function with signature function(x, arg, evaluations) that returns
the functions' (approximated/interpolated) values at locations x based on
the function evaluations available at locations arg.
Available evaluator-functions:
tf_approx_linear for linear interpolation without extrapolation (i.e.,
zoo::na.approx() with na.rm = FALSE) – this is the default,
tf_approx_spline for cubic spline interpolation, (i.e., zoo::na.spline()
with na.rm = FALSE),
tf_approx_fill_extend for linear interpolation and constant extrapolation
(i.e., zoo::na.fill() with fill = "extend")
tf_approx_locf for "last observation carried forward" (i.e.,
zoo::na.locf() with na.rm = FALSE)
tf_approx_nocb for "next observation carried backward" (i.e.,
zoo::na.locf() with na.rm = FALSE, fromLast = TRUE).
See tf:::zoo_wrapper and tf:::tf_approx_linear, which is simply
zoo_wrapper(zoo::na.approx, na.rm = FALSE), for examples of
implementations of this.
a tfd-object (or a data.frame/matrix for the conversion
functions, obviously).
# turn irregular to regular tfd by evaluating on a common grid: f <- c( tf_rgp(1, arg = seq(0, 1, length.out = 11)), tf_rgp(1, arg = seq(0, 1, length.out = 21)) ) tfd(f, arg = seq(0, 1, length.out = 21)) set.seed(1213) f <- tf_rgp(3, arg = seq(0, 1, length.out = 51)) |> tf_sparsify(0.9) # does not yield regular data because linear extrapolation yields NAs # outside observed range: tfd(f, arg = seq(0, 1, length.out = 101)) # this "works" (but may not yield sensible values..!!) for # e.g. constant extrapolation: tfd(f, evaluator = tf_approx_fill_extend, arg = seq(0, 1, length.out = 101)) plot(f, col = 2) tfd(f, arg = seq(0, 1, length.out = 151), evaluator = tf_approx_fill_extend ) |> lines()# turn irregular to regular tfd by evaluating on a common grid: f <- c( tf_rgp(1, arg = seq(0, 1, length.out = 11)), tf_rgp(1, arg = seq(0, 1, length.out = 21)) ) tfd(f, arg = seq(0, 1, length.out = 21)) set.seed(1213) f <- tf_rgp(3, arg = seq(0, 1, length.out = 51)) |> tf_sparsify(0.9) # does not yield regular data because linear extrapolation yields NAs # outside observed range: tfd(f, arg = seq(0, 1, length.out = 101)) # this "works" (but may not yield sensible values..!!) for # e.g. constant extrapolation: tfd(f, evaluator = tf_approx_fill_extend, arg = seq(0, 1, length.out = 101)) plot(f, col = 2) tfd(f, arg = seq(0, 1, length.out = 151), evaluator = tf_approx_fill_extend ) |> lines()
f: R -> R^d)tfd_mv represents vector-valued functional data – vectors of functions
, such as movement
trajectories or other multivariate-output curves.
tfd_mv(data, ...) ## S3 method for class 'list' tfd_mv(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'array' tfd_mv(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'data.frame' tfd_mv( data, id = 1, arg = 2, value = 3, domain = NULL, evaluator = tf_approx_linear, ... ) ## S3 method for class 'tf_mv' tfd_mv(data, arg = NULL, domain = NULL, evaluator = NULL, ...) ## Default S3 method: tfd_mv(data, arg = NULL, domain = NULL, ...) as.tfd_mv(data, ...) ## Default S3 method: as.tfd_mv(data, ...) ## S3 method for class 'tf_mv' as.tfd_mv(data, ...)tfd_mv(data, ...) ## S3 method for class 'list' tfd_mv(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'array' tfd_mv(data, arg = NULL, domain = NULL, evaluator = tf_approx_linear, ...) ## S3 method for class 'data.frame' tfd_mv( data, id = 1, arg = 2, value = 3, domain = NULL, evaluator = tf_approx_linear, ... ) ## S3 method for class 'tf_mv' tfd_mv(data, arg = NULL, domain = NULL, evaluator = NULL, ...) ## Default S3 method: tfd_mv(data, arg = NULL, domain = NULL, ...) as.tfd_mv(data, ...) ## Default S3 method: as.tfd_mv(data, ...) ## S3 method for class 'tf_mv' as.tfd_mv(data, ...)
data |
one of: a (named) |
... |
forwarded to the univariate |
arg |
evaluation grid, see |
domain |
range of |
evaluator |
inter-/extrapolation function, see |
id, value
|
for the |
A tfd_mv object of length n bundles d univariate tfd() vectors
(one per output dimension / component), each of length n. All numeric work
(evaluation, arithmetic, smoothing, ...) is delegated to these components, so
regular and irregular sampling, the choice of evaluator, etc. all behave
exactly as in the univariate case – and components may even live on
different argument grids. Use tfb_mv() for a basis representation.
a tfd_mv object (a vctrs vector of length n).
tf_mv classes inherit from "tf" only for the purpose of tf_domain(),
type predicates (is_tf(), is_tf_mv(), ...) and S4 generic reuse.
Behaviour on tf_mv comes only from explicitly registered .tf_mv
methods: any generic without one aborts with a classed
tf_mv_method_unimplemented condition. The earlier promise of automatic
"right thing component-wise" dispatch via inheritance was incorrect –
silent fall-through produced wrong-shape results or deep internal errors,
so it has been replaced with fail-fast stubs. The stubbed (i.e., not
implemented) verbs are listed in tf_mv_unimplemented; design of real
component-wise semantics is tracked at
https://github.com/tidyfun/tf/issues/255. When you need to distinguish
univariate-only from any-tf inside a helper, use is_tf_1d(): it returns
TRUE for tfd / tfb and FALSE for tfd_mv / tfb_mv.
tfb_mv() for basis representation; tf_components(),
tf_ncomp() and the $ operator to access components.
Other tf_mv-class:
plot.tf_mv(),
tf_arclength(),
tf_geom,
tf_mv_methods,
tfb_mfpc(),
tfb_mv()
# (a) from a (named) list of univariate tfd vectors -- one per component: traj <- tfd_mv(list(x = tf_rgp(3), y = tf_rgp(3))) traj tf_ncomp(traj) traj$x # (b) from a list of matrices (one [curve, arg] matrix per component): t <- seq(0, 1, length.out = 50) mx <- matrix(sin(2 * pi * outer(1:3, t)), nrow = 3) my <- matrix(cos(2 * pi * outer(1:3, t)), nrow = 3) tfd_mv(list(x = mx, y = my), arg = t) # (c) from a 3-d array with dimensions [curve, arg, component]: arr <- array(c(mx, my), dim = c(3, 50, 2), dimnames = list(NULL, NULL, c("x", "y"))) tfd_mv(arr, arg = t) # (d) from a long data.frame (id, arg, one value column per component): df <- data.frame( id = rep(1:3, each = 50), arg = rep(t, times = 3), x = as.vector(t(mx)), y = as.vector(t(my)) ) tfd_mv(df, id = "id", arg = "arg", value = c("x", "y"))# (a) from a (named) list of univariate tfd vectors -- one per component: traj <- tfd_mv(list(x = tf_rgp(3), y = tf_rgp(3))) traj tf_ncomp(traj) traj$x # (b) from a list of matrices (one [curve, arg] matrix per component): t <- seq(0, 1, length.out = 50) mx <- matrix(sin(2 * pi * outer(1:3, t)), nrow = 3) my <- matrix(cos(2 * pi * outer(1:3, t)), nrow = 3) tfd_mv(list(x = mx, y = my), arg = t) # (c) from a 3-d array with dimensions [curve, arg, component]: arr <- array(c(mx, my), dim = c(3, 50, 2), dimnames = list(NULL, NULL, c("x", "y"))) tfd_mv(arr, arg = t) # (d) from a long data.frame (id, arg, one value column per component): df <- data.frame( id = rep(1:3, each = 50), arg = rep(t, times = 3), x = as.vector(t(mx)), y = as.vector(t(my)) ) tfd_mv(df, id = "id", arg = "arg", value = c("x", "y"))
tf
These methods and operators mostly work arg-value-wise on tf objects, see
vctrs::vec_arith() etc. for implementation details.
## S3 method for class 'tfd' e1 == e2 ## S3 method for class 'tfd' e1 != e2 ## S3 method for class 'tfb' e1 == e2 ## S3 method for class 'tfb' e1 != e2 ## S3 method for class 'tfd' vec_arith(op, x, y, ...) ## S3 method for class 'tfb' vec_arith(op, x, y, ...) ## S3 method for class 'tfd' Math(x, ...) ## S3 method for class 'tfb' Math(x, ...) ## S3 method for class 'tf' Summary(...) ## S3 method for class 'tfd' cummax(...) ## S3 method for class 'tfd' cummin(...) ## S3 method for class 'tfd' cumsum(...) ## S3 method for class 'tfd' cumprod(...) ## S3 method for class 'tfb' cummax(...) ## S3 method for class 'tfb' cummin(...) ## S3 method for class 'tfb' cumsum(...) ## S3 method for class 'tfb' cumprod(...)## S3 method for class 'tfd' e1 == e2 ## S3 method for class 'tfd' e1 != e2 ## S3 method for class 'tfb' e1 == e2 ## S3 method for class 'tfb' e1 != e2 ## S3 method for class 'tfd' vec_arith(op, x, y, ...) ## S3 method for class 'tfb' vec_arith(op, x, y, ...) ## S3 method for class 'tfd' Math(x, ...) ## S3 method for class 'tfb' Math(x, ...) ## S3 method for class 'tf' Summary(...) ## S3 method for class 'tfd' cummax(...) ## S3 method for class 'tfd' cummin(...) ## S3 method for class 'tfd' cumsum(...) ## S3 method for class 'tfd' cumprod(...) ## S3 method for class 'tfb' cummax(...) ## S3 method for class 'tfb' cummin(...) ## S3 method for class 'tfb' cumsum(...) ## S3 method for class 'tfb' cumprod(...)
e1 |
an |
e2 |
an |
op |
An arithmetic operator as a string. |
x |
a |
y |
a |
... |
|
Operations on tfd-objects do not extrapolate functions on a common grid first,
they operate on the function at argument values that both objects have in
common.
With the exception of addition and
multiplication, operations on tfb-objects first evaluate the data on their
arg, perform computations on these evaluations and then convert back to an
tfb- object, so a loss of precision should be expected – especially so for
small spline bases and/or very wiggly data.
Equality checks of functional objects are even more iffy than usual for computer math and not very reliable.
Note that max and min are not guaranteed to be maximal/minimal over the
entire domain, only at the argument values used for computation.
See examples below, many more are in tests/testthat/test-ops.R.
a tf- or logical vector with the computed result.
tf_fwise() for scalar summaries of each function in a tf-vector
set.seed(1859) f <- tf_rgp(4) 2 * f == f + f sum(f) == f[1] + f[2] + f[3] + f[4] log(exp(f)) == f plot(f, points = FALSE) lines(range(f), col = 2, lty = 2) f2 <- tf_rgp(5) |> exp() |> tfb(k = 25) layout(t(1:3)) plot(f2, col = gray.colors(5)) plot(cummin(f2), col = gray.colors(5)) plot(cumsum(f2), col = gray.colors(5)) # ?tf_integrate for integrals, ?tf_fwise for scalar summaries of each functionset.seed(1859) f <- tf_rgp(4) 2 * f == f + f sum(f) == f[1] + f[2] + f[3] + f[4] log(exp(f)) == f plot(f, points = FALSE) lines(range(f), col = 2, lty = 2) f2 <- tf_rgp(5) |> exp() |> tfb(k = 25) layout(t(1:3)) plot(f2, col = gray.colors(5)) plot(cummin(f2), col = gray.colors(5)) plot(cumsum(f2), col = gray.colors(5)) # ?tf_integrate for integrals, ?tf_fwise for scalar summaries of each function
tf objects across argument valuesThese will return a tf object containing the respective functional
statistic. See tf_fwise() for scalar summaries
(e.g. tf_fmean for means, tf_fmax for max. values) of each entry
in a tf-vector.
## S3 method for class 'tf' mean(x, ...) ## S3 method for class 'tf' median(x, na.rm = FALSE, depth = "MBD", ...) sd(x, na.rm = FALSE) ## Default S3 method: sd(x, na.rm = FALSE) ## S3 method for class 'tf' sd(x, na.rm = FALSE) var(x, y = NULL, na.rm = FALSE, use) ## Default S3 method: var(x, y = NULL, na.rm = FALSE, use) ## S3 method for class 'tf' var(x, y = NULL, na.rm = FALSE, use) ## S3 method for class 'tf' summary(object, ..., depth = "MBD") ## S3 method for class 'tf_mv' summary(object, ..., depth = "MBD")## S3 method for class 'tf' mean(x, ...) ## S3 method for class 'tf' median(x, na.rm = FALSE, depth = "MBD", ...) sd(x, na.rm = FALSE) ## Default S3 method: sd(x, na.rm = FALSE) ## S3 method for class 'tf' sd(x, na.rm = FALSE) var(x, y = NULL, na.rm = FALSE, use) ## Default S3 method: var(x, y = NULL, na.rm = FALSE, use) ## S3 method for class 'tf' var(x, y = NULL, na.rm = FALSE, use) ## S3 method for class 'tf' summary(object, ..., depth = "MBD") ## S3 method for class 'tf_mv' summary(object, ..., depth = "MBD")
x |
a |
... |
optional additional arguments. |
na.rm |
logical. Should missing values be removed? |
depth |
depth method used for computing the median and central region.
See |
y |
|
use |
an optional character string giving a
method for computing covariances in the presence
of missing values. This must be (an abbreviation of) one of the strings
|
object |
a |
a tf object with the computed result.summary.tf returns a tf-vector with the mean function, the functional
median, the pointwise min and max of x, and the pointwise min and max
of the central half of the functions in x, as defined by the chosen
depth (default "MBD", see tf_depth()).
Other tidyfun summary functions:
fivenum(),
functionwise,
median.tf_mv()
set.seed(123) x <- tf_rgp(1) * 1:5 mean(x) median(x, depth = "pointwise") sd(x) var(x) summary(x)set.seed(123) x <- tf_rgp(1) * 1:5 mean(x) median(x, depth = "pointwise") sd(x) var(x) summary(x)
Coerces x to character and returns syntactically valid, unique
identifiers. Empty strings are replaced with "NA" before
deduplication. If x already has no duplicates it is returned
unchanged.
unique_id(x)unique_id(x)
x |
any input that can be coerced to character. |
A character vector of unique, syntactically valid names of
the same length as x.
Other tidyfun utility functions:
ensure_list(),
in_range(),
tf_arg(),
tf_zoom()
unique_id(c("a", "a", "b")) unique_id(c(1, 1, 2))unique_id(c("a", "a", "b")) unique_id(c(1, 1, 2))
vctrs methods for tf objectsThese functions are the extensions that allow tf vectors
to work with vctrs.
## S3 method for class 'tfd_mv.tfd_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_mv.tfb_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_mv.tfb_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_mv.tfd_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_mv.tfd_mv' vec_cast(x, to, ...) ## S3 method for class 'tfb_mv.tfb_mv' vec_cast(x, to, ...) ## S3 method for class 'tfd_mv.tfb_mv' vec_cast(x, to, ...) ## S3 method for class 'tfb_mv.tfd_mv' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_reg.tfd_irreg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_reg.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_reg.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfd_irreg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfd_irreg' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfd_irreg' vec_ptype2(x, y, ...)## S3 method for class 'tfd_mv.tfd_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_mv.tfb_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_mv.tfb_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_mv.tfd_mv' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_mv.tfd_mv' vec_cast(x, to, ...) ## S3 method for class 'tfb_mv.tfb_mv' vec_cast(x, to, ...) ## S3 method for class 'tfd_mv.tfb_mv' vec_cast(x, to, ...) ## S3 method for class 'tfb_mv.tfd_mv' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfd_irreg.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfb_spline' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfb_fpc' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfb_spline.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfd_reg' vec_cast(x, to, ...) ## S3 method for class 'tfb_fpc.tfd_irreg' vec_cast(x, to, ...) ## S3 method for class 'tfd_reg.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_reg.tfd_irreg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_reg.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_reg.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfd_irreg' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfd_irreg.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_spline.tfd_irreg' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfb_spline' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfb_fpc' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfd_reg' vec_ptype2(x, y, ...) ## S3 method for class 'tfb_fpc.tfd_irreg' vec_ptype2(x, y, ...)
x |
Vectors to cast. |
y |
vectors to cast. |
... |
For |
to |
Type to cast to. If |
Notes on vec_cast:
Use tf_rebase() to change the representations of tf-vectors,
these methods are only for internal use –
automatic/implicit casting of tf objects is tricky
because it's hard to determine automatically whether such an operation would
lose precision (different bases with different expressivity? different
argument grids?), and it's not generally clear which instances of which
tf-subclasses should be considered the "richer" objects.
Rules for casting:
If the casted object's domain would not contain the entire original domain,
no casting is possible (would lose data).
Every cast that evaluates (basis) functions on different arg values is a lossy cast,
since it might lose precision (vctrs::maybe_lossy_cast).
As long as the casted object's domain contains the entire original domain:
every tfd_reg, tfd_irreg or tfb can always be cast into an equivalent
tfd_irreg (which may also change its evaluator and domain).
every tfd_reg can always be cast to tfd_reg (which may change its evaluator and domain)
every tfb can be cast losslessly to tfd (regular or irregular,
note it's lossless only on the original arg-grid)
Any cast of a tfd into tfb is potentially lossy (because we don't know how expressive the chosen basis is)
Only tfb with identical bases and domains can be cast into one another losslessly
Casts deliberately keep the source's arg-grid: they re-express
functions in the target's representation rather than re-evaluate them on
the target's grid, so a cast result need not be identical to the target
prototype (a deliberate deviation from the strict vctrs cast invariant
that avoids silently coarsening data during type unification).
for vec_cast: the casted tf-vector, for vec_ptype2: the common prototype
vctrs::vec_cast(), vctrs::vec_ptype2()
set.seed(1) x <- tf_rgp(3) xi <- tf_sparsify(x) # different tf subtypes combine to their common type: c(x, xi) vctrs::vec_ptype_full(vctrs::vec_c(x, xi))set.seed(1) x <- tf_rgp(3) xi <- tf_sparsify(x) # different tf subtypes combine to their common type: c(x, xi) vctrs::vec_ptype_full(vctrs::vec_c(x, xi))