Skip to main content

lpeer

Function lpeer 

Source
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 via famm::build_subject_map.
  • config — penalty family and λ selection (same as peer()).

§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);