Quickstart¶
This page walks through the core objects of fdatools with the Berkeley growth data, which ships inside the package (no download needed). Every code block runs as written, top to bottom.
import numpy as np
import fdatools as fdt
growth = fdt.datasets.load_growth()
growth.age.shape, growth.hgtf.shape # 31 ages, 54 girls
1. A basis¶
A basis is a fixed set of simple functions. Every curve is written as a
weighted sum of them. fdatools has seven basis types: BSpline, Fourier,
Monomial, Exponential, Power, Constant and Polygonal.
basis = fdt.BSpline(domain=(1.0, 18.0), n_basis=12) # cubic by default (order 4)
phi = basis(growth.age) # (31, 12): each column is one function
d2 = basis(growth.age, deriv=2) # second derivatives, exact
R = basis.penalty(2) # roughness penalty: integral of (D^2 phi)(D^2 phi)'
W = basis.gram() # integral of phi phi'
2. Curves: FData¶
An FData holds the coefficients of many curves in one basis. Call it like a
function to evaluate it.
coefs, *_ = np.linalg.lstsq(phi, growth.hgtf, rcond=None)
girls = fdt.FData(coefs, basis)
girls.n_curves # 54
heights = girls(np.array([2.0, 10.0, 18.0])) # (3, 54)
speed = girls.derivative() # exact: a lower-order spline, no projection
speed(np.array([12.0])).shape # (1, 54)
Arithmetic and statistics return new FData objects:
mean_curve = girls.mean()
deviations = girls.center() # girls - mean, curve by curve
spread = girls.std()
first_two = girls[0:2]
doubled = first_two * 2.0
norm_sq = fdt.inprod(girls[0], girls[0]) # L2 inner product, same as girls[0] @ girls[0]
covariance = girls.cov() # a BiFData surface v(s, t)
covariance(np.array([5.0]), np.array([5.0, 10.0])).shape
3. Differential operators: LDO¶
A linear differential operator (LDO) is a weighted sum of derivatives. It is
used as a roughness penalty and can be evaluated on a curve.
accel = fdt.LDO(2) # D^2, curvature
harmonic = fdt.LDO.harmonic(period=365.0) # (2 pi / 365)^2 D + D^3, for yearly data
girls(np.array([10.0]), accel).shape # apply the operator, then evaluate
basis.penalty(accel).shape # (12, 12)
4. Smoothing with automatic λ¶
smooth() fits curves by penalised least squares. With lam="gcv" it picks
the smoothing parameter λ that minimises generalised cross-validation (GCV).
from fdatools.smoothing import smooth
fine = fdt.BSpline(domain=(1.0, 18.0), n_basis=20)
fit = smooth(growth.hgtf, growth.age, basis=fine, lam="gcv", penalty=3)
fit.lam, fit.df # chosen lambda and equivalent degrees of freedom
fit.fd.n_curves # 54 smooth curves
fit.gcv.shape # one GCV score per curve
fixed_df = smooth(growth.hgtf, growth.age, basis=fine, lam="df=10")
round(fixed_df.df, 6) # 10.0
Shape constraints are one argument away: constraint="monotone" fits curves
that never decrease (like height), constraint="positive" fits curves that
stay above zero.
5. Functional PCA¶
FPCA is a scikit-learn estimator. It finds the main modes of variation
(the harmonics) and the score of every curve on each mode.
from fdatools.decomposition import FPCA
pca = FPCA(n=3).fit(fit.fd)
pca.varprop # share of variance per harmonic
pca.scores.shape # (54, 3)
pca.harmonics.n_curves # 3 harmonic curves
6. pandas and xarray¶
With the pandas extra installed, curves move in and out of data frames.
# requires: pandas
frame = girls[0:3].to_pandas(np.linspace(1.0, 18.0, 5))
frame.shape
Next¶
- The tutorials work through six full analyses.
- Migrating from R
fdamaps each R function to fdatools. - The API reference documents every argument.