pub fn lpeer(
data: &FdMatrix,
y: &[f64],
argvals: &[f64],
subject_map: &[usize],
config: &PeerConfig,
) -> Result<LpeerResult, FdarError>Expand description
Fit the longitudinal PEER scalar-on-function regression model with subject random effects.
Extends peer to grouped/repeated-measures data by reducing the
functional predictor to FPC scores (via fdata_to_pc_1d) and calling
famm::fit_scalar_mixed_model for subject-level random intercepts.
The PEER penalty (via config) regularises β(t) through the same λ
dispatch as peer(); the mixed model then replaces the OLS second pass
with a GLS+REML-EM pass over the FPC scores.
ncomp cap: min(n − 1, m, 10) — documented; prevents over-parameterisation
at small n.
§Arguments
data— n×m functional predictor matrix.y— scalar response vector, length n.argvals— evaluation grid, length m.subject_map— subject index per observation, length n. Non-contiguous IDs are re-indexed internally viafamm::build_subject_map.config— penalty family and λ selection (same aspeer()).
§Errors
Returns FdarError::InvalidDimension on dimension mismatches,
FdarError::InvalidParameter when n_subjects < 2 or argvals is
non-monotone/non-finite, and FdarError::ComputationFailed when the
mixed-model produces non-finite coefficients.
§Example
use fdars_core::matrix::FdMatrix;
use fdars_core::peer::{lpeer, PeerConfig, PeerPenalty, LambdaChoice};
let (n, m) = (12_usize, 5_usize);
let argvals: Vec<f64> = (0..m).map(|i| i as f64 / (m - 1) as f64).collect();
let mut data = FdMatrix::zeros(n, m);
let mut y = vec![0.0_f64; n];
// 3 subjects × 4 observations each
let subject_map: Vec<usize> = (0..n).map(|i| i / 4).collect();
for i in 0..n {
for j in 0..m {
let xi = ((i * m + j) as f64 * 0.3).sin();
data[(i, j)] = xi;
y[i] += xi * 0.5;
}
}
let config = PeerConfig {
penalty: PeerPenalty::Ridge,
lambda: LambdaChoice::Fixed(1e-2),
};
let fit = lpeer(&data, &y, &argvals, &subject_map, &config).unwrap();
assert_eq!(fit.beta.len(), m);
assert!(fit.sigma2_subject >= 0.0);
assert!(fit.sigma2_resid >= 0.0);
let preds = fit.predict(&data, &argvals).unwrap();
assert_eq!(preds.len(), n);