Skip to contents

Estimates the measurement model once, on its own, and then estimates the group-class structure with that measurement held fixed. This is the staged workflow used when the measurement solution is meant to be decided before the grouping question is asked, so that adding group classes cannot move the profiles they are meant to describe.

Usage

fit_staged(
  data,
  vars,
  id,
  n_profiles,
  n_group_classes = 2L,
  measurement = NULL,
  variance_model = c("varying", "equal"),
  n_starts = 10L,
  max_iter = 1000L,
  tol = 1e-08,
  min_variance = 1e-06,
  seed = NULL,
  missing = c("error", "fiml"),
  covariance_model = c("diagonal", "full"),
  categorical = character(),
  min_probability = 1e-10,
  time = NULL
)

Arguments

data

A data frame containing indicators and a group identifier.

vars

Unique character vector of continuous indicator column names.

id

Name of the observed group identifier column. Character, factor, or numeric identifiers are supported; missing identifiers are not. Required here: this model has a second level by construction, so it has no single-level form and does not take multilpa()'s id = NULL.

n_profiles

Positive integer number of individual profiles.

n_group_classes

Number of latent group classes to estimate in the second stage. Must be at least two; one would leave nothing to estimate.

measurement

Optional fitted multilpa model to use as the first stage, so that a measurement solution already chosen and inspected is carried forward rather than refitted. Its profiles, indicators and measurement options must match the ones requested here, and it must have one group class: a multi-class fit already estimates group structure and is not a measurement-only first stage. When NULL, the first stage is fitted here with one group class.

variance_model

Either "varying" (profile-specific variances or covariance matrices) or "equal" (shared across profiles).

n_starts

Number of EM starts, used for both stages.

max_iter

Nonnegative integer maximum number of EM updates per start. max_iter = 0 performs no update. With start, it returns the model evaluated at exactly those values, whatever n_starts is, so that logLik() scores a parameter set supplied from elsewhere rather than the best of some random initializations that were never asked for. Without start there is nothing to evaluate at, so the random initializations are scored and the highest is returned.

tol

Positive relative log-likelihood tolerance. Convergence requires absolute change no greater than tol * (1 + abs(previous log likelihood)).

min_variance

Positive lower bound on each variance, or each covariance eigenvalue for full covariance, in squared input units. This defines a constrained maximum-likelihood problem. Bound-active estimates are explicitly reported and generate a warning.

seed

Optional random seed: any whole number set.seed() accepts, negative ones included. With a supplied seed, the caller's random-number state is restored on exit.

missing

"error" rejects missing indicators; "fiml" maximizes the observed-data likelihood under an ignorable missingness mechanism (MAR). Missing indicators are integrated out, not filled in for likelihood fitting. This holds with membership covariates too; the covariates themselves must be complete (latents_bad_data).

covariance_model

"diagonal" assumes conditional independence; "full" estimates within-profile residual covariances.

categorical

Character vector naming indicators to treat as categorical. Each is modelled by unrestricted, profile-specific response probabilities over its observed categories, which is the latent class measurement model. Binary, ordinal and unordered indicators are all handled by the same unrestricted parameterization; numeric, integer, logical, character and factor columns are accepted. Indicators not named here stay Gaussian, so naming a subset fits a mixed-mode model.

min_probability

Positive lower bound on every categorical response probability, defining a constrained maximum-likelihood problem in the same way min_variance does for Gaussian indicators.

time

Optional name of a column giving each observation's position within its group, such as a wave, occasion or course number. The model does not use it; it is stored so that get_results(x, "sequences"), get_results(x, "sequence_summary") and plot(what = "sequences") can read the assignments back in order. Values must be complete and unique within each group.

Value

A multilpa object for the second stage, so that every accessor, diagnostic and method works on it unchanged. Its measurement parameters are exactly the first stage's. It additionally carries fixed, naming the held blocks; n_parameters, counting only the parameters this stage estimated; and n_parameters_with_measurement, which adds the held measurement back. Use get_results() with what = "stages" for a tidy two-row summary of both stages.

Details

The second stage treats the measurement solution as known, so its Wald standard errors (parameter_inference()'s default), information criteria and likelihood-ratio comparisons are conditional on that solution and are narrower than they would be if the measurement had been estimated jointly. parameter_inference(fit, method = "bootstrap") removes that conditioning for the standard errors and intervals: every resample of the groups is staged again, measurement first, so the replicates carry the first stage's sampling variability into the second stage, and the table also reports the measurement parameters with their own errors. A measurement supplied by the caller is re-estimated on each resample with the same options, since the resample is new data. The conditioning of the criteria and likelihood comparisons is a property of staging itself, and it is the reason both parameter counts are reported: compare staged fits with one another using n_parameters, and compare a staged fit with a jointly estimated one using n_parameters_with_measurement, remembering that the staged likelihood is not the joint maximum and the comparison is descriptive.

See also

multilpa() with fixed for finer control over which blocks are held, and starting_values() with what = "measurement" for the values a stage hands on.

Examples

set.seed(7)
example_data <- data.frame(
  school = rep(seq_len(30), each = 8),
  score_a = stats::rnorm(240), score_b = stats::rnorm(240)
)
staged <- fit_staged(example_data, c("score_a", "score_b"), "school",
                     n_profiles = 2, n_group_classes = 2, n_starts = 2,
                     seed = 1)
get_results(staged, what = "stages")
#>         stage group_classes            fixed log_likelihood parameters
#> 1 measurement             1             <NA>      -671.8928          9
#> 2  membership             2 means, variances      -671.8928          3
#>   parameters_with_measurement converged
#> 1                           9      TRUE
#> 2                          11      TRUE
get_results(staged, what = "profile_probabilities")
#>   group_class profile probability group_class_probability
#> 1           1       1  0.97827865                     0.5
#> 2           1       2  0.02172135                     0.5
#> 3           2       1  0.97827865                     0.5
#> 4           2       2  0.02172135                     0.5