| efa_simulate | R Documentation |
Draws data from a population correlation matrix, given either directly or
built from a factor model. The population correlation is either supplied in
R, or assembled from a loading matrix Lambda, the factor intercorrelations
Phi, and the unique variances Psi as
R = Lambda\, Phi\, Lambda' + Psi, standardized to a correlation matrix.
marginals chooses the marginal distribution of the drawn cases, categories
discretizes them into ordered categories, missing imposes a missing-data mechanism,
and a misfit target perturbs the population with model error; see Details.
efa_simulate(
N = NULL,
Lambda = NULL,
Phi = NULL,
Psi = NULL,
R = NULL,
model_error = c("CB", "TKL", "WB", "none"),
target_rmsea = NULL,
target_cfi = NULL,
marginals = c("normal", "empirical", "VM", "IG"),
marginal_data = NULL,
n_factors = NULL,
skewness = NULL,
kurtosis = NULL,
force_pd = FALSE,
categories = NULL,
match = NULL,
missing = c("none", "MCAR", "MAR", "MNAR"),
missing_prop = NULL,
missing_strength = NULL,
missing_predictor = NULL,
missing_vars = NULL,
n_datasets = 1L,
seed = NULL,
return_pop = FALSE
)
N |
numeric. Number of cases (rows) to draw per dataset. Required unless
|
Lambda |
matrix. A |
Phi |
matrix. The |
Psi |
numeric vector or matrix. The unique variances: either a length- |
R |
matrix. A |
model_error |
character. The method used to perturb the population so the factor model
fits it imperfectly ("model error"): one of |
target_rmsea |
numeric. The population RMSEA the factor model should have relative to
the perturbed population, a single number strictly in |
target_cfi |
numeric. Only used with |
marginals |
character. The marginal distribution of the drawn data: one
of |
marginal_data |
matrix or data frame. Only used with
|
n_factors |
numeric. Only used with |
skewness |
numeric. Only used with |
kurtosis |
numeric. Only used with |
force_pd |
logical. Used with |
categories |
numeric or list. Requests ordinal output by discretizing each
variable into ordered categories. Either a count of equally probable categories
(a single value applied to every variable or a length- |
match |
character. Only used with |
missing |
character. An optional missing-data mechanism to impose on the drawn
data: one of |
missing_prop |
numeric. Only used when |
missing_strength |
numeric. Only used with |
missing_predictor |
integer or character. Only used with |
missing_vars |
integer or character. Only used when |
n_datasets |
numeric. The number of datasets to draw. Default is 1. With more than one, a list of datasets is returned. |
seed |
numeric. Optional seed for reproducible draws. When supplied, the
caller's random-number stream is saved and restored, so the call leaves the
global RNG state unchanged. Default is |
return_pop |
logical. If |
Provide the population either as a ready correlation matrix in R, or through
the model components Lambda, Phi, and Psi; the two ways are mutually
exclusive. When the model components are used, Phi defaults to the identity
matrix (orthogonal factors) and Psi defaults to the unique variances that
make the population a correlation matrix (1 - \mathrm{diag}(Lambda\, Phi\,
Lambda')); the assembled covariance is standardized with
stats::cov2cor() so a non-standardized Psi still yields a correlation
matrix. With the default Psi, a factor model whose implied communalities
exceed 1 (a Heywood case) leaves no unique variance and is rejected; a Psi
you supply is instead only required to give positive variances and a
positive-semidefinite (a mathematically valid, internally consistent
correlation/covariance structure) population. Cases with normal marginals (the
default) are drawn through a matrix square root of the population correlation –
a Cholesky factor, or a symmetric eigen square root when it is singular (e.g. a
communality of exactly 1).
With marginals = "empirical", the iterative rank-matching algorithm of Ruscio
and Kaczetow (2008) reproduces the population correlation while each variable
takes the empirical marginal distribution of the matching column of
marginal_data (resampled with replacement). Only the marginals of
marginal_data are used; its own correlations are ignored, and the drawn columns
follow the population's variables, not those of marginal_data.
With marginals = "VM" (Vale-Maurelli, 1983) or "IG" (the independent-generator
method; Foldnes & Olsson, 2016), the cases reproduce the population correlation
while carrying non-normal marginals with the target skewness and (excess)
kurtosis. The Vale-Maurelli family does not span every valid non-normal
distribution (Foldnes & Grønneberg, 2015); "IG" covers distributions "VM"
cannot. Not every (skewness, kurtosis) pair is attainable – every distribution
needs excess kurtosis of at least skewness^2 - 2, and either method covers a smaller
region still – so an unreachable request is rejected, as is a "VM" intermediate
correlation matrix that is not positive definite unless force_pd allows it.
With categories, the drawn data are discretized into ordered categories (an integer
code 1 to K) at the thresholds that reproduce the requested category proportions
(Olsson, 1979): the standard-normal quantiles for marginals = "normal", and for
marginals = "VM" those quantiles mapped through the same Fleishman (1978) cubic the
draw uses, so the requested proportions are reproduced on the non-normal scale too. Under
marginals = "IG" the thresholds stay on the standard-normal scale while the data do
not, so the achieved proportions depart from the request systematically rather than by
sampling noise, and only the number of categories is guaranteed; the same holds for a
"VM" variable whose Fleishman cubic is not increasing over its own thresholds and the
tails beyond them, which keeps the normal-scale thresholds and is reported with a
warning. This is more likely with strong skewness/kurtosis or very unequal category
proportions; the warning names the affected variable.
Because categorization attenuates product-moment correlations, the categorized
data's Pearson correlation is smaller in magnitude than the population correlation;
under non-normal marginals its polychoric correlation departs from the population as
well. Ordinal output is not available with marginals = "empirical". Empty categories
left by a draw are reported with a warning, as they destabilize the polychoric
correlation and the factor analysis.
With missing, missing values are introduced into the drawn data under a chosen
mechanism (Rubin, 1976), each variable holed at a target expected rate
missing_prop. "MCAR" draws an independent mask, so missingness is unrelated to
the data. "MAR" and "MNAR" set each case's missing probability by a logistic
model of a standardized predictor: another variable for "MAR" (chosen by
missing_predictor) or the variable's own value for "MNAR", with slope
missing_strength. The mechanism acts on the drawn (latent) values, so when
categories also discretizes the data the missingness is keyed on the underlying
value, not the category code. For "MAR" the predictor is evaluated on the complete
drawn values, so whether the mechanism is ignorably MAR depends on which variables
carry missing values. By default every variable is holed, which leaves a variable's MAR
predictor itself missing for roughly a missing_prop fraction of the cases whose
missingness it drove. This breaks ignorability: the mechanism is then MAR conditional
on the complete data but not ignorable for an analyst who sees only the observed
data. As a result, estimators that are consistent under ignorable MAR – cor_method = "fiml" in efa_fit(), or the multiple imputation behind efa_mi() – keep a residual
bias that grows with missing_prop and missing_strength. Restricting the holed
variables with missing_vars and pointing
missing_predictor at variables outside that set makes every predictor fully observed,
which is ignorably MAR and recovers the unbiasedness those estimators are advertised
with. The returned matrix carries the NAs, which the correlation estimators handle
downstream.
With model_error, the population is perturbed away from the exact factor
structure so the q-factor model (q = ncol(Lambda)) fits it only approximately,
at a prescribed misfit; exact factor structures are unrealistic (see
target_rmsea). The perturbation is applied once to
the population, and the achieved misfit of the specified generating model is computed
with the same fit-index formulas efa_fit() uses and returned in the model_error
element. It needs a factor-model population with residual degrees of freedom and an
exact factor structure (a diagonal Psi), and is orthogonal to the marginal, ordinal,
and missing-data options. Three methods are available. "CB" (Cudeck & Browne,
1992) matches the target RMSEA to numerical precision and keeps the q-factor
model the exact minimizer (the CFI follows as a derived quantity). "TKL" (Tucker,
Koopman & Linn, 1969) adds minor common factors tuned so the achieved RMSEA – and,
optionally, CFI – match the target(s); with a single target the match is close, with
both it is a compromise, reported with a warning when the two cannot be reconciled.
"WB" (Wu & Browne, 2015) draws the population from
an inverse-Wishart distribution around the model-implied correlation; its calibration
applies to the best-fitting model, so the reported misfit of the generating model
is systematically larger than the target – about 1.4 times for a typical 12-variable,
3-factor model. Use "CB" when the reported RMSEA must equal the target.
Replicated draws (n_datasets > 1) are generated in parallel across
replicates with future.apply; a parallel plan can be selected with
future::plan() (the default plan runs sequentially). Each replicate is
assigned its own reproducible random-number stream, so with a fixed seed the
output is identical regardless of the number of workers.
An object of class efa_simulated, a list containing:
data |
The simulated data: an |
population |
The |
model_error |
|
settings |
The call's key arguments ( |
Printing the object shows a compact summary.
Cudeck, R., & Browne, M. W. (1992). Constructing a covariance matrix that yields a specified minimizer and a specified minimum discrepancy function value. Psychometrika, 57(3), 357-369. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/BF02295424")}
Fleishman, A. I. (1978). A method for simulating non-normal distributions. Psychometrika, 43(4), 521-532. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/BF02293811")}
Foldnes, N., & Grønneberg, S. (2015). How general is the Vale-Maurelli simulation approach? Psychometrika, 80(4), 1066-1083. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/s11336-014-9414-0")}
Foldnes, N., & Olsson, U. H. (2016). A simple simulation technique for nonnormal data with prespecified skewness, kurtosis, and covariance matrix. Multivariate Behavioral Research, 51(2-3), 207-219. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/00273171.2015.1133274")}
MacCallum, R. C. (2003). 2001 Presidential Address: Working with imperfect models. Multivariate Behavioral Research, 38(1), 113-139. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1207/S15327906MBR3801_5")}
Olsson, U. (1979). Maximum likelihood estimation of the polychoric correlation coefficient. Psychometrika, 44(4), 443-460. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/BF02296207")}
Rubin, D. B. (1976). Inference and missing data. Biometrika, 63(3), 581-592. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1093/biomet/63.3.581")}
Ruscio, J., & Kaczetow, W. (2008). Simulating multivariate nonnormal data using an iterative algorithm. Multivariate Behavioral Research, 43(3), 355-381. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/00273170802285693")}
Tucker, L. R., Koopman, R. F., & Linn, R. L. (1969). Evaluation of factor analytic research procedures by means of simulated correlation matrices. Psychometrika, 34(4), 421-459. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/BF02290601")}
Vale, C. D., & Maurelli, V. A. (1983). Simulating multivariate nonnormal distributions. Psychometrika, 48(3), 465-471. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/BF02293687")}
Wu, H., & Browne, M. W. (2015). Quantifying adventitious error in a covariance structure as a random effect. Psychometrika, 80(3), 571-600. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/s11336-015-9451-3")}
efa_power(), whose simulation mode draws its replicate data sets with this
function, and efa_fit() for analysing the simulated data.
Other data simulation:
print.efa_simulated()
# Build a population from a shipped loading pattern and factor correlations
Lambda <- population_models$loadings$baseline
Phi <- population_models$phis_3$moderate
# Draw one normal dataset of 500 cases (the data live in $data)
sim <- efa_simulate(N = 500, Lambda = Lambda, Phi = Phi, seed = 42)
dim(sim$data)
# Return only the population correlation matrix
R_pop <- efa_simulate(Lambda = Lambda, Phi = Phi, return_pop = TRUE)$population
# Draw several datasets at once from a supplied correlation matrix
sims <- efa_simulate(N = 500, R = R_pop, n_datasets = 3, seed = 42)
length(sims$data)
# Reproduce the population correlation but with skewed, empirical marginals
# (here from a chi-squared source with one column per variable)
src <- matrix(rchisq(200 * nrow(Lambda), df = 3), ncol = nrow(Lambda))
dat_emp <- efa_simulate(N = 500, Lambda = Lambda, Phi = Phi,
marginals = "empirical", marginal_data = src, seed = 42)
# Draw skewed, leptokurtic data with the Vale-Maurelli method
dat_vm <- efa_simulate(N = 500, Lambda = Lambda, Phi = Phi, marginals = "VM",
skewness = 1.5, kurtosis = 4, seed = 42)
# Draw five-category ordinal data whose polychoric correlation matches R
dat_ord <- efa_simulate(N = 500, Lambda = Lambda, Phi = Phi,
categories = 5, match = "polychoric", seed = 42)
# Draw data with 15% missing at random, driven by a neighbouring item
dat_mar <- efa_simulate(N = 500, Lambda = Lambda, Phi = Phi, missing = "MAR",
missing_prop = 0.15, seed = 42)
colMeans(is.na(dat_mar$data))
# An ignorably MAR design: only the first nine items are holed, each driven by one of
# the last nine, which stay complete
dat_ign <- efa_simulate(N = 500, Lambda = Lambda, Phi = Phi, missing = "MAR",
missing_prop = 0.15, missing_vars = 1:9,
missing_predictor = 10:18, seed = 42)
colMeans(is.na(dat_ign$data))
# Add realistic model error: a population the model fits with RMSEA of about .05
# (Cudeck-Browne, the default method; the achieved fit is reported)
sim_me <- efa_simulate(N = 500, Lambda = Lambda, Phi = Phi,
target_rmsea = 0.05, seed = 42)
sim_me$model_error$rmsea
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.