S3 Classes and Methods for Tidy Functional Data
Overview
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.
Internal
tf_rgp()no longer depends onmvtnormorpracma. GP draws are now generated by a direct eigen-based sampler (the symmetric square rootV D^{1/2} V^Tof the covariance) that reproduces the previousmvtnorm::rmvnorm(method = "eigen")draws bit-for-bit underset.seed()and handles rank-deficient kernels (e.g. squared-exp with zero nugget) correctly.tf_smooth.tfd(method = "savgol")now inlines a small Savitzky–Golay filter in place of thepracma::savgol()dependency.
Bug fixes
tf_evaluate()no longer returns values at the wrong positions when the requested arg contains duplicates (#236).tf_integrate(f, definite = FALSE)for irregulartfdwith n > 1 no longer crashes; the antiderivative's per-curve grids are kept as a list (#237).
Show all changes in 0.5.0Hide the rest of the changes in 0.5.0
Math.tfd()/Math.tfb()now forward...to the underlying op soround(x, digits),log(x, base),signif(x, digits), etc. honor their extra arguments instead of silently dropping them (#246).tf_integrate()on irregulartfdno longer silently returnsNAunder default limits; for irregular input the defaults are now each curve's own observed arg range (i.e., the range of itstf_arg()values). Pass explicitlower/upper(or an extrapolating evaluator) to override (#253).
Vector-valued functional data
This release introduces first-class support for vector-valued (multivariate)
functional data -- functions whose codomain is R^d -- alongside the existing
univariate tfd/tfb classes.
tfd_mv()andtfb_mv(): newvctrs-based S3 classes for vector-valued functional data, holding several component functions per observation on a shared domain. Constructors accept named lists oftfd/tfbvectors or list-columns of matrices.tfb_mfpc()implements multivariate functional principal component analysis (Happ & Greven, 2018) fortf_mvdata: a single set of scalar scores per curve shared across all components, with vector-valued eigenfunctions. Component weighting is configurable ("inverse_variance"default,"snr","equal", or user-supplied). New data can be projected onto a fitted basis viatf_rebase()/vec_cast(). Accessorstf_mfpc_scores(),tf_mfpc_efunctions()and the predicateis_tfb_mfpc().- Multivariate registration:
tf_register()gainsmethod = "srvf_mv"for jointly aligning the components oftf_mvcurves via the multivariate SRVF framework, andtf_register_shape()provides elastic shape registration (rotation/translation/scale-invariant) viafdasrvf. - New geometry verbs for
tf_mv(and where meaningful for univariatetf):tf_norm(),tf_inner(),tf_tangent(),tf_arclength(). - Component accessors (
tf_ncomp(),tf_components(),tf_component()),tf_split()/tf_combine()extensions and[/[[methods for extracting, replacing and recombining components. - Function-wise scalar summaries
tf_fmean(),tf_fvar()andtf_fsd()return component-wise matrices fortf_mvobjects. tf_interpolate(),tf_fwise(),tf_sparsify()andtf_jiggle()now have component-wisetf_mvmethods;tf_sparsify()andtf_jiggle()keep shared component grids by default viasame_arg = TRUE.tf_where()/tf_anywhere()work ontf_mvobjects with *joint* conditions across components, referenced by name (e.g.tf_where(f, x > 0 & y < 1)); there is novaluecolumn fortf_mvinput. Components must share a common grid, orargmust be supplied explicitly.quantile()works ontf_mvobjects, returning the *component-wise* pointwise quantiles: atf_mvwith one curve per requested probability inprobs, exactly asquantile.tf()does per component (na.rm/probs/typeare forwarded).points()works ontf_mvobjects, mirroringlines.tf_mv(): in"trajectory"mode (d == 2) it overlays the paired(x(t), y(t))points with per-curve graphical-parameter recycling; in"facet"mode it overlays each component onto the current device.tf_depth()gains atf_mvmethod: a weighted componentwise aggregation of the (centrality) univariate depths, with aweightsargument mirroringtfb_mfpc()("equal"default,"inverse_variance", or a numeric vector). The up-down ordering index"MHI"has no canonical vector-valued analogue and aborts with a pointer totf_order()(#273).median(),summary()andfivenum()ontf_mvnow select *observed* vector-valued curves via a single joint-depth index (one curve across all components), fixing the previous component-wise "chimera" where each component could come from a different observation. Pointwise entries (mean, min/max, the central-half range) remain component-wise (#273).- New generic
tf_order()with atf_mvmethod:tf_order(f, by = "norm")(orby = <component name>) orders vector-valued curves by an explicit scalar reduction.sort(),rank()andxtfrm()remain permanently undefined fortf_mv-- there is no canonical total order onR^d-- so basesort()/order()/rank()fail fast rather than fabricate an order (#273).
Contract change
is_tf()now returnsTRUEfortf_mvas well as univariatetfd/tfb. Code that branched onis_tf()to mean "univariatetf" should switch to the new predicateis_tf_1d()."arg"and"id"are reserved and cannot be used as component names -- they collide with the grid and curve-id columns of long-format conversions.- Constructing a
tf_mvfrom components with differing domains now *warns* when wideningtfdcomponents to the union domain (evaluations outside the observed range areNA) and *aborts* fortfbcomponents, where basis evaluation outside the fitted range would extrapolate, i.e. fabricate values. - Component-wise operations on a
tfb_mfpc(tf_smooth(),tf_derive(),tf_zoom(),tf_integrate(),mean()/sd()/var(),Summarygroup generics) now consistently demote to valid per-componenttfb_fpcrepresentations with a one-time warning, like arithmetic already did -- previously they silently produced objects that abort on later use. tf_fmax(),tf_fmin()andtf_fmedian()ontf_mvreturn ann x dcurves-x-components matrix liketf_fmean()/tf_fsd()(previously: a misnamed interleaved vector).tfb_fpc()andtfb_mfpc()abort informatively when the input contains completely missing curves (partially missing evaluations continue to be handled by the soft-impute SVD); re-scoring new data withNAcurves viatf_rebase()/vec_cast()yieldsNAscores andNAentries.
Tabular export of components on differing grids
as.data.frame.tf_mv(unnest = TRUE)gains agridsargument controlling where components are evaluated when they live on different argument grids:"union"(default, previous behavior) evaluates every component on each curve's union grid, interpolating inside the observed range;"component"evaluates each component strictly on its own grid (or onarg), so no values are fabricated where a component was not observed -- the faithful export used bytidyfun::tf_unnest(). For shared grids both agree.
More bug fixes (pre-release review)
- Empty prototypes (
tfd(),tfb(),tfd_mv(list())and friends) carry the sentinel domainc(NA, NA)and now combine cleanly with populated vectors in allvctrspaths (vec_c(),vec_rbind(),c(), casts) -- binding rows onto an initially emptytfcolumn works again. tfb_mv()on an existingtfb_mvwith an explicitbasisargument re-fits in the requested basis instead of silently returning the old one; changing the basis kind converts throughtfd().tfb_mv()/tfb_mfpc()on raw lists/arrays route constructor arguments (arg,domain) and basis arguments to the right place instead of forwarding everything everywhere.tfd_mv()on 3-d arrays keeps length-1 curve/arg margins and curve names.tf_derive()andtf_integrate()ontf_mvaccept per-componentarglists, consistent withtf_interpolate().Summarygroup generics ontf_mvno longer recycleNAmasks across operands of different lengths.tf_arclength():method = "polyline"honorslower/upperwithout creating near-duplicate vertices, andmethod = "derive"no longer NA-poisons irregular curves that do not span the full domain.- Indefinite
tf_integrate()on irregulartfdsnaps user-supplied limits to (almost-)coinciding grid points instead of constructing invalid objects. tf_register()works fortf_mvinputs whose components live on different grids;tf_register_shape()returns a user-suppliedtemplateunchanged fromtf_template(); single-componentsrvf_mvdelegates to univariate elastic registration and template-free single-curve registration is rejected with an explanation instead of crashing insidefdasrvf.
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-04
- NOTE12 OK, 1 NOTE2026-08-01
- OK14 OK2026-04-09
- WARNING12 OK, 2 WARNING2026-04-07
- OK14 OK2026-03-10
Documentation
- Help pages
- 58 (4 internal)includes a package overview page
- Examples that run
- 95%52 run in a plain check (4 of them under a condition) · 3 only when donttest examples are enabled (R CMD check --as-cran)
- Exported functions with examples
- 98%
- Documented parameters
- 98%
- Return-value docs
- 100%
- Help pages citing references
- 16%
Downloads
Repository
- PRs merged (all time)
- 93%
- Median days to close, 50 most recently updated closed issues
- 34
- Median days to close, 50 most recently updated closed PRs
- 1
Stars over time
Forks over time
Releases over time
Issues over time
PRs over time
Commits over time
13 development-tooling and community-health practices detected across 9 families in the upstream repository
Checks run against github.com/tidyfun/tf on 2026-10-11.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-09-03 · The repository has a site deploy workflow
pkgdown site last built 2026-07-15
Show all practicesHide 5 practices
This repository shows signs of AI coding tools.
- Claude Codefirst seen 2025-04-22Seen in the repository: CLAUDE.mdNamed in .Rbuildignore: .claude, CLAUDE.mdNamed in .gitignore: .claudeCommits: 156 by its own account · at least 103 crediting it in the message
- GitHub Copilotfirst seen 2026-02-19Pull request: opened by its own account
- Codexfirst seen 2026-07-13Named in .Rbuildignore: .codex
- Claude CodePull requests: 34 from outside contributors, first on 2026-02-09
- Claude Fable 535 commits · Jun to Jul 2026
- Claude Opus 4.813 commits · May to Jun 2026
- Claude Fable 5.112 commits · Sep 2026
- Claude Opus 4.612 commits · Feb to Mar 2026
- Claude Opus 4.52 commits · Jan 2026
Some of these counts are a minimum, because the search stopped before the oldest commits.
Dependencies
Installing tf adds 10 packages (9 with compiled code, 4.1 MB of source tarballs). Heaviest: vctrs 1.0 MB, rlang 766 KB, zoo 675 KB.
Code & Tests
Datasets
People & History
Show 4 peopleHide 4 people
Pick two releases to compare their code metrics.
- 0.5.0Latest2026-07-14 · current release · diff ↗ ·
added 29 exports
tf_component<-, as.tfb_mv, as.tfd_mv, fpc_wsvd, is_tf_1d, is_tf_mv, is_tfb_mfpc, is_tfb_mv, is_tfd_mv, savgol, tf_arclength, tf_component, tf_components, tf_distance, tf_inner, tf_mfpc_efunctions, tf_mfpc_scores, tf_ncomp, tf_norm, tf_order, tf_register_shape, tf_reparam_arclength, tf_rotations, tf_scales, tf_speed, tf_tangent, tfb_mfpc, tfb_mv, tfd_mv - RR 4.6.0 released · 2026-04-24
- 0.4.12026-04-07 · diff ↗
- 0.4.02026-03-17 · diff ↗ ·
removed 7 exports
vec_cast.tfb_spline, vec_cast.tfd_irreg, vec_cast.tfd_reg, vec_ptype2.tfb_fpc, vec_ptype2.tfb_spline, vec_ptype2.tfd_irreg, vec_ptype2.tfd_regadded 14 exports
fivenum, rank, tf_align, tf_aligned, tf_combine, tf_estimate_warps, tf_inv_warps, tf_invert, tf_landmarks_extrema, tf_register, tf_split, tf_template, tf_warp, tfb_spline - RR 4.5.0 released · 2025-04-11
- 0.3.42024-05-22 · diff ↗
- RR 4.4.0 released · 2024-04-24
- 0.3.32024-03-28 · diff ↗
- 0.3.22024-03-18
- RR 4.3.0 released · 2023-04-21
Package metadata
- First published
- 2024-03-18
- Total releases
- 6 / 2 yrs
- License
- AGPL (>= 3) OSI
- Minimum R
- ≥ 4.1
- Bundled data
- 16 KB / 3 files
- Download size
- 300 KB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("tf")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-18, which the citation names so these numbers can be found later. More on citing and the projects behind them.