Changelog
R2spa 0.0.4
New Features
vcov_corrected()andtspa(corrected_se = TRUE)gain anengineargument, and its default is now"analytic": a refit-free, deterministic influence-function closed form (PLAN 16, sections 2.4 and 4.3),J = -H^{-1} CwithH(the log-likelihood Hessian over the free params) andC(the cross-derivative w.r.t. the fixedfsL/fsTentries) obtained by central-differencing the analytic log-likelihood score. It covers single- and multi-group models, saturated and restricted (df > 0) structural models, and mean-structure models, and is a pure function of the base fit +vfsLT(bit-reproducible, no refits, no optimizer jitter)."fd"(the original central finite-difference Jacobian) is retained as the A/B reference and the transparent fallback for a shape the analytic form cannot handle; the two engines agree to the finite-difference noise floor whenever"analytic"applies. The corrected-SE golden tolerances are tightened from the FD’s cross-platform drift floor (1e-2) to the analytic bit-stability floor (1e-8).tspa_mx_model()now auto-derives its measurement inputs fromget_fs.merMod()results as well: withse_fs/fsL/fsT/fsball omitted, the per-cluster 3-DfsL/fsTarray attributes become definition-variable matrices referencing the result’s own per-cluster*_by_*/ev_*/ecov_*columns (one row per cluster, exact non-pooled correction);merModresults carry nofsb, so the score intercepts stay fixed at zero.Product factor-score indicators now carry fixed measurement-error covariances in the stage-2 model: products sharing a factor score (e.g.
xmandxz) have correlated measurement errors (the shared score’s error enters both), andtspa()computes the error covariance for every pair of product latents from the stage-1fsL/fsT/psiattributes (new pure-matrix helperfs_prod_ecov(): a diagonal score-error matrix — disjoint-indicator CFAs — reduces the shared-factor pair totau_jl s_i^2, the non-shared pair’s latent covariance times the shared score’s error variance; local-mode separate-models results reduce to zero) and emits it as a fixedfs_v1 ~~ fs_v2statement. Works on both the single-factor (se_fs) and the multi-factor (fsT/fsL) paths, for bothtspa(product = TRUE)and the manual workflow (product columns pre-computed withget_fs(product = )/compute_fs_prod()and listed inse_fs), removing the first-order (n-independent) attenuation of the product coefficients that the previously free covariance absorbed. Data lacking the stage-1 attributes (e.g. acbind()’dget_fs()result) with two or more product latents is rejected with an informative error (remedy: pass the un-cbind()’d result). Single-group models (v1).Re-integrated the product factor-score vignette from
.quarantine/asproduct-factor-scores(vignettes/product-factor-scores.Rmd): the rewrittenget_fs_int-vignette.Rmdoncompute_fs_prod()/get_fs(product = )/tspa(product = )(including the fixed product-indicator error covariances above; the example DGP is scaled so theylatent has population variance exactly 1, so the estimates are read directly against the simulated coefficients).Add computation of reliability function in
get_fscore()(#81)Add functions of obtaining tidy-ed factor scores data for
get_fscore()(#79)get_fs()now supports multi-groupmirtmodels (MultipleGroupClass): per-observation factor scores are extracted from the whole fit, carry a trailinggroupcolumn (the model’s group levels,NAfor completely-missing rows) and a per-group ()psiattribute, with each observation using its own group’s factor covariance.Re-integrated
grand_standardized_solution()/ legacy aliasgrandStandardizedSolution()(from.quarantine/): grand-standardized path coefficients with delta-method SEs for (multi)grouplavaanfit objects.tspa()now accepts multi-factor mirt factor scores — single- and multi-groupget_fs()output (per-observationfsL/fsTlists) — by reducing them to one representative set per group viareduce(default"mean"), the same per-unit pooling path as FIML/merMod; completely-missing mirt rows are dropped from the reduction.tspa()now accepts aget_fs()result asdatadirectly: whenfsT/fsL(multi-factor) orse_fs(single-factor) are omitted they are derived from the result’sfsT/fsL/fsbattributes or itsfs_<v>/fs_<v>_sescore columns; explicit arguments always take precedence.tspa_mx_model()now accepts aget_fs()result asdatadirectly: whense_fs/fsL/fsT/fsbare all omitted, the measurement inputs are derived from the result’s attributes — constant quantities (complete data,local = TRUE,format = "list") become fixed numerics, while per-row (mirt,local = TRUEFIML) and per-pattern (single-group FIML) quantities become definition variables referencing the result’s own*_by_*/ev_*/ecov_*columns, with theint_fs_*score-intercept columns appended automatically from thefsbattribute. Explicit arguments always take precedence, a non-get_fs()frame fails fast with an actionable message instead of the old misleading error, and there is no pooling (the OpenMx route is exact-or-fail, unliketspa(reduce = )); multigroup remains refused in Phase 1.get_fs()gainslocal = TRUE: each latent is scored from its own local measurement model (per-construct stage 1, the canonical 2S-PA setup) instead of the single joint multi-factor model; the merged result carries the usual multi-factor attributes with exactly-zero cross-terms (block-diagonalfsT/fsL/psi, zeroecov_*columns) and feedstspa()directly.modelmay be a single string (strict per-latent=~grammar) or a character vector / named list of complete single-factor model strings (the escape hatch).vfsLT(hencetspa(corrected_se = TRUE)),prior_cov, andreliabilityare not supported inlocalmode (v1).New exported
compute_fs_prod()+get_fs(product = ): double-mean-centered product factor-score indicators for pairs of distinct latents in a single-grouplavaanmodel (v1). For each requested pair (productas an"a:b + c:d"string, a list of length-2 name pairs, or a 2-column matrix/data frame) the result gainsfs_a:fs_b(the product indicator),fs_a:fs_b_se(per-row standard error) andfs_a:fs_b_ld(implied loading). The SE uses the general joint-model formulase_P^2 = tau_a s_b^2 + tau_b s_a^2 + s_a^2 s_b^2 + c^2 + 2 tau_ab c(derivation in?compute_fs_prod), so correlated factors, cross-loadings, and error covariances are handled — the separate-single-factor special case it reduces to. Under FIML the SE/loading resolve per observed-indicator pattern; the output feedstspa()directly via the existing product-score auto-alias.get_fs()gains aproductargument forwarding tocompute_fs_prod()(single-grouplavaanmodels only; rejected withlocal = TRUEand for multi-group models, v1).tspa()gains an opt-inproductargument (defaultFALSE): whenTRUE, the double-mean-centered product indicators for every model latent that names the product of two of the model’s factor scores — by concatenation (xmforxandm) or in lavaan’s interaction syntax (x:m, rendered under the concatenated name) — are computed on the fly and incorporated into the stage-2 measurement model — in the single-factor (score-scale) path the product SE joinsse_fs(per-group pooled, loading 1, as before), and in the multi-factor path the product latent gets a fixed implied loadinggammaand fixed error variancese_P^2from the (pooled)fsL/fsTand thepsiattribute. Ana:btoken whose parts are not both factor scores (e.g.x:gwithgan observed covariate) is not claimed and passes through to lavaan as an ordinary interaction; an explicit product SE may be keyed by either the render name or thea:btoken. Single-group models only (v1); not supported withcorrected_se = TRUE; naming the same pair twice (x:mandxm) or a render name colliding with another model variable is an error; pre-existing product columns (either orientation) are used as-is, so the manualget_fs(product = )+se_fsworkflow is unchanged.
Breaking changes
- The quarantined student function
get_fs_int()(and its test file) is removed; its functionality is superseded byget_fs(product = )/compute_fs_prod(), which keep its column-naming convention (fs_a:fs_b,fs_a:fs_b_se,fs_a:fs_b_ld) but use the corrected joint-model SE formula. -
augment_lav_predict()’s factor-score standard-error columns are renamed from the legacyse_fs_*to the canonicalfs_*_seused byget_fs(),get_fs_lavaan(), andfs_indiv()(#85), so all per-row APIs now agree on column names. The documentedev_*/ecov_*ordering difference (upper-triangular inaugment_lav_predict(), lower-triangular elsewhere) is intentional and unchanged.
Improvements
- The stage-2 model string attached to
tspa()fits (thetspaModelattribute) is now rendered with normalized operator spacing (lhs =~ rhs,lhs ~~ rhs) and withoutc()for single-value fixed statements (e.g.ind60 =~ 1 * fs_ind60instead ofind60=~ c(1) * fs_ind60); multigroup statements keepc(v1, v2); fitted models, parameter tables, and covariance are unchanged. -
tspa(corrected_se = TRUE)now supports multigroup fits, andgrandStandardizedSolution()threadsvcov(object)(or an explicitacov_par = vcov(corrected_fit)) so a corrected fit yields corrected grand-standardized SEs with unchanged point estimates; the re-integratedcorrected-sevignette documents the in-place single- and multigroup correction. -
grandStandardizedSolution()now reports user-fixed structural slopes (~ k*var): itsest.stdis the user value rescaled by the (grand) SD ratio and itsseis the first-order delta approximation, matchinglavaan::standardizedSolution()(which also reports a delta SE for fixed slopes). Previously a single fixed structural path rejected the whole solution. Free slopes are unchanged (still anchored by free position); a structural regression outside the beta matrix (e.g. observed-on-observed) is still rejected. - Update naming for
get_fscore()(#79)- Rename
vctoev(error variance-covariance) for better consistency
- Rename
Bug Fixes
-
tspa_mx_model()no longer mis-specifies off-diagonal factor-score covariances whenlavaanify()presents a~~row with the (lhs, rhs) pair reversed relative to the score order: the definition-variable lookup now falls back to the transposed triangle, so a lower-triangle-onlyfsT(the documented and the auto-derived convention) is honored. Previously thec(1)definition-variable sentinel leaked into the model as a fixed unit covariance between the scores, and such fits (e.g. multi-factor mirt per-row models, single-group FIML per-pattern models) aborted with “implied covariance not positive definite”. - Fix a bug in the
se_fsargument intspa()(#90). -
grandStandardizedSolution()now assigns standardized estimates and SEs to partable rows by their global free position instead of assuming the structural paths follow the beta matrix column-major order; the two agree only by accident (e.g. single-predictor models), so models with multiple endogenous variables per group could reportest.std/se/CIs on the wrong rows.
Documentation
- Documented the mean-structure convention difference between
tspa()(lavaan, which fixes the exogenous latent mean at zero and estimates the factor-score mean) andtspa_mx_model()(OpenMx, which fixes the score residual means at zero and estimates the latent means): the two routes fit the same model, so only the unidentifiable mean split differs — compare on the covariance quantities. Noted in both functions’ docs, the OpenMx vignette, and a regression test. - Updated vignettes for:
- tspa-growth-vignette (#50)
- missing-data (#79) — re-integrated and modernized: the per-row scoring of missing-data fits is explained, and the stage-2 examples use
tspa_mx_model()(per-row definition variables) withtspa(reduce = )pooling contrasted - 2S-PA with OpenMx and IRT (mirt): the multidimensional example now uses the auto-derived measurement inputs (no hand-rolled
cross_load/err_covmatrices) - efa-score: complete-case (listwise) correlation instead of FIML
lavCor, so stage 1 (EFA) and stage 2 share one data basis;n.rotations = 1pinspsych::fa()against the psych 2.6.5faRotations()bug
R2spa 0.0.3
Add function
tspa_plot()for bivariate and residual plots (#23)get_fs()gains argumentcorrected_fsTfor computing corrected error estimates (#50)New function
vcov_corrected()for computing corrected SEs (#39)New function
get_fs_lavaan()for computing factor scores and relevant matrices directly from alavaanoutput (#61)Initial support for 2S-PA with OpenMx with
tspa_mx()-
Update naming of relevant matrices when computing factor scores:
-
fsT: error covariance of factor scores -
fsL: loading matrix of factor scores -
fsb: intercepts of factor scores -
scoring_matrix: weights for computing factor scores from items
-
-
New vignettes for:
- Corrected error variance of factor scores (#50)
- Corrected standard errors incorporating uncertainty in measurement parameters of factor scores (#39)
- Using 2S-PA with EFA scores
- Using 2S-PA with OpenMx and definition variables (PR #57)
- Latent interaction with categorical indicators (#27)
- Growth modeling
Better error messages for
tspa()(#53)Support mean structure and growth model (#36, #19)
Clean up code with
lintr(#33)
R2spa 0.0.2
Use
pkgdownto create website, with GitHub action (#22)get_fs()now returns a list with multi-group models (#29).New function
grandStandardizedSolution()computes standardized solution based on grand mean and grand SD (#13).tspa()gains argumentvcandcross_loadings, which is useful for factor scores obtained from multi-factor models (#7). Seevignette("Multi-Factor Measurement Model").