| Title: | Measurement Error Analysis and Correction Under Identification Restrictions |
|---|---|
| Description: | Implements methods for analyzing latent variable models with measurement error correction, including Item Response Theory (IRT) models. Provides tools for various correction methods such as Bayesian Markov Chain Monte Carlo (MCMC), over-imputation, bootstrapping for robust standard errors, Ordinary Least Squares (OLS), and Instrumental Variables (IV) based approaches. Supports flexible specification of observable indicators and groupings for latent variable analyses in social sciences and other fields. Methods are described in a working paper (2025) <doi:10.48550/arXiv.2507.22218>. Also includes corrections for panel fixed-effects and differencing designs, latent treatment-effect moderators in randomized experiments, and multi-measure reliability bounds. |
| Authors: | Connor Jerzak [aut, cre], Stephen Jessee [aut] |
| Maintainer: | Connor Jerzak <[email protected]> |
| License: | GPL-3 |
| Version: | 1.3.0 |
| Built: | 2026-10-16 23:49:48 UTC |
| Source: | https://github.com/cjerzak/lpmec-software |
A function to build the environment for lpmec. Builds a conda environment in which 'JAX', 'numpyro', and 'numpy' are installed. Users can also create a conda environment where 'JAX' and 'numpy' are installed themselves.
build_backend(conda_env = "lpmec", conda = "auto")build_backend(conda_env = "lpmec", conda = "auto")
conda_env |
(default = |
conda |
(default = |
Invisibly returns NULL; this function is used for its side effects
of creating and configuring a conda environment for lpmec.
This function requires an Internet connection.
You can find out a list of conda Python paths via: Sys.which("python")
## Not run: # Create a conda environment named "lpmec" # and install the required Python packages (jax, numpy, etc.) build_backend(conda_env = "lpmec", conda = "auto") # If you want to specify a particular conda path: # build_backend(conda_env = "lpmec", conda = "/usr/local/bin/conda") ## End(Not run)## Not run: # Create a conda environment named "lpmec" # and install the required Python packages (jax, numpy, etc.) build_backend(conda_env = "lpmec", conda = "auto") # If you want to specify a particular conda path: # build_backend(conda_env = "lpmec", conda = "/usr/local/bin/conda") ## End(Not run)
This helper analyzes observable indicators and returns a numeric vector
of 1 or -1 for use with the orientation_signs
argument in lpmec. Each sign is chosen so that the correlation
between the oriented indicator and either the outcome Y or the
first principal component of the indicators is positive.
infer_orientation_signs(Y, observables, method = c("Y", "PC1"))infer_orientation_signs(Y, observables, method = c("Y", "PC1"))
Y |
Numeric outcome vector. Only used when |
observables |
A matrix or data frame of binary observable indicators. |
method |
Character string specifying how to orient the indicators.
Default is |
A numeric vector of length ncol(observables) containing
1 or -1.
set.seed(1) Y <- rnorm(10) obs <- data.frame(matrix(sample(c(0,1), 20, replace = TRUE), ncol = 2)) infer_orientation_signs(Y, obs)set.seed(1) Y <- rnorm(10) obs <- data.frame(matrix(sample(c(0,1), 20, replace = TRUE), ncol = 2)) infer_orientation_signs(Y, obs)
KnowledgeVoteDuty is a modified set of responses to a small set of questions on the American National Election Study's 2024 Time Series Study. These data only include respondents who had non-missing values on all of the variables included, dropping respondents with one or more missing values.
data(KnowledgeVoteDuty)data(KnowledgeVoteDuty)
A data frame with 3,059 observations and 5 variables:
Whether respondents feel that voting is a duty or a choice. Values range from 1 to 7, with 1 being "Very strongly a duty" and 7 being "Very strongly a choice," created based on variable V241218x.
Dummy variable (0 or 1) for whether respondent correctly stated the length of a U.S. Senate term. Created based on variable V241612.
Dummy variable (0 or 1) for whether respondent correctly identified "Foreign aid" from a list as the category the federal government spends the least on. Created based on variable V241613.
Dummy variable (0 or 1) for whether respondent correctly identified the political party that currently has the most members in the U.S. House of Representatives. Created based on variable V241614.
Dummy variable (0 or 1) for whether respondent correctly identified the political party that currently has the most members in the U.S. Senate. Created based on variable V241615.
American National Election Studies. 2024. ANES 2024 Time Series Study Full Release [dataset and documentation]. Available at electionstudies.org.
data(KnowledgeVoteDuty) voteduty <- KnowledgeVoteDuty$voteduty knowledge <- scale(rowMeans(KnowledgeVoteDuty[ , -1])) summary(lm(voteduty ~ knowledge))data(KnowledgeVoteDuty) voteduty <- KnowledgeVoteDuty$voteduty knowledge <- scale(rowMeans(KnowledgeVoteDuty[ , -1])) summary(lm(voteduty ~ knowledge))
Implements latent variable models with measurement error correction
lpmec( Y, observables, observables_groupings = colnames(observables), orientation_signs = NULL, make_observables_groupings = FALSE, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), boot_basis = 1:length(Y), bootstrap_method = c("n_out_of_n", "m_out_of_n", "subsampling", "auto"), boot_m = NULL, boot_m_rule = c("power", "fixed", "grid_stability"), boot_m_exponent = 0.7, boot_m_grid = NULL, boot_m_replace = NULL, boot_ci_type = c("auto", "root", "root_calibrated", "percentile", "rbc"), boot_alpha = 0.05, boot_rate = c("sqrt_n", "custom"), boot_tau = NULL, boot_calibration_n = 25L, boot_calibration_inner_n_boot = NULL, boot_calibration_cut_grid = c(0.005, 0.01, 0.015, 0.02, 0.025, 0.035, 0.05), boot_calibration_tail = c("separate", "equal_tail"), boot_calibration_seed = NULL, boot_rbc_item_counts = NULL, boot_rbc_n_subsets = 10L, boot_rbc_seed = NULL, partition_set = NULL, fix_partitions = TRUE, seed = NULL, return_intermediaries = TRUE, ordinal = FALSE, estimation_method = "em", latent_estimation_fn = NULL, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", anchor_parameter_id = NULL, n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), conda_env = "lpmec", conda_env_required = FALSE )lpmec( Y, observables, observables_groupings = colnames(observables), orientation_signs = NULL, make_observables_groupings = FALSE, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), boot_basis = 1:length(Y), bootstrap_method = c("n_out_of_n", "m_out_of_n", "subsampling", "auto"), boot_m = NULL, boot_m_rule = c("power", "fixed", "grid_stability"), boot_m_exponent = 0.7, boot_m_grid = NULL, boot_m_replace = NULL, boot_ci_type = c("auto", "root", "root_calibrated", "percentile", "rbc"), boot_alpha = 0.05, boot_rate = c("sqrt_n", "custom"), boot_tau = NULL, boot_calibration_n = 25L, boot_calibration_inner_n_boot = NULL, boot_calibration_cut_grid = c(0.005, 0.01, 0.015, 0.02, 0.025, 0.035, 0.05), boot_calibration_tail = c("separate", "equal_tail"), boot_calibration_seed = NULL, boot_rbc_item_counts = NULL, boot_rbc_n_subsets = 10L, boot_rbc_seed = NULL, partition_set = NULL, fix_partitions = TRUE, seed = NULL, return_intermediaries = TRUE, ordinal = FALSE, estimation_method = "em", latent_estimation_fn = NULL, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", anchor_parameter_id = NULL, n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), conda_env = "lpmec", conda_env_required = FALSE )
Y |
A vector of observed outcome variables |
observables |
A matrix of observable indicators used to estimate the latent variable |
observables_groupings |
A vector specifying groupings for the observable indicators. Default is column names of observables. |
orientation_signs |
(optional) A numeric vector of length equal to the number of columns in 'observables', containing 1 or -1 to indicate the desired orientation of each column. If provided, each column of 'observables' will be oriented by this sign before analysis. Default is NULL (no orientation applied). |
make_observables_groupings |
Logical. If TRUE, creates dummy variables for each level of the observable indicators. Default is FALSE. |
n_boot |
Non-negative integer. Number of bootstrap iterations. Use
|
n_partition |
Positive integer. Number of split-half partitions for each
bootstrap iteration. When |
partition_aggregation |
Aggregation strategy for combining estimates across
partitions within each bootstrap iteration. Default is |
partition_aggregation_probs |
Numeric vector of length 2 used by
|
boot_basis |
Vector of indices or grouping variable for stratified bootstrap. Default is 1:length(Y). |
bootstrap_method |
Resampling method for uncertainty. Options are
|
boot_m |
Optional exact m for m-out-of-n bootstrap or subsampling. |
boot_m_rule |
Rule used when |
boot_m_exponent |
Exponent used by |
boot_m_grid |
Optional candidate grid for m-sensitivity diagnostics. |
boot_m_replace |
Optional logical override for row replacement in
m-out-of-n/subsampling. By default, replacement is used for
|
boot_ci_type |
Confidence interval type. |
boot_alpha |
Confidence interval tail probability. Default is 0.05. |
boot_rate |
Rate used by root-scaled intervals. The current formal path
uses |
boot_tau |
Optional function used when |
boot_calibration_n |
Positive integer. Number of outer calibration
subsamples used when |
boot_calibration_inner_n_boot |
Optional positive integer. Number of
inner resamples within each calibration subsample. Defaults to
|
boot_calibration_cut_grid |
Candidate one-sided tail probabilities for
nested root interval calibration. Values must be greater than |
boot_calibration_tail |
Calibration mode. |
boot_calibration_seed |
Optional seed for the nested calibration stage. |
boot_rbc_item_counts |
Optional integer vector of observable-group
counts used to estimate the leading finite-M bias when
|
boot_rbc_n_subsets |
Positive integer. Number of item subsets drawn at
each value of |
boot_rbc_seed |
Optional seed for the item-subset schedule used by
|
partition_set |
Optional user-supplied fixed partition list. Each element
must contain |
fix_partitions |
Logical. If |
seed |
Optional seed used for reproducible partitions and resamples. |
return_intermediaries |
Logical. If TRUE, returns intermediate results. Default is TRUE. |
ordinal |
Logical indicating whether the observable indicators are ordinal (TRUE) or binary (FALSE). |
estimation_method |
Character specifying the estimation approach. Options include:
|
latent_estimation_fn |
Custom function for estimating latent trait from |
mcmc_control |
A list indicating parameter specifications if MCMC used.
|
conda_env |
A character string specifying the name of the conda environment to use
via |
conda_env_required |
A logical indicating whether the specified conda environment
must be strictly used. If |
This function implements a latent variable analysis with measurement error correction.
It fits the original sample and, when n_boot >= 1, performs bootstrap
resampling for uncertainty estimates. Each original or bootstrap sample is
analyzed with one or more split-half partitions. For each partition,
it calls the lpmec_onerun function to estimate latent variables and apply various correction methods.
The results are then aggregated across partitions and bootstrap iterations to produce final estimates
and, when bootstrap draws are available, bootstrap standard errors.
For partition_aggregation = "median", the finite-partition median is
a nonsmooth aggregation rule. The ordinary n-out-of-n row bootstrap remains
available through bootstrap_method = "n_out_of_n" for backward
compatibility. The formal nonsmooth-functional route is
bootstrap_method = "subsampling" or "m_out_of_n" with
boot_ci_type = "root" or "root_calibrated". In that route,
the same realized partition set is held fixed across the original sample
and all resamples, each resample reruns the full latent-score and correction
pipeline, and confidence intervals invert the empirical distribution of
sqrt(m) * (theta_boot - theta_hat) at the original sqrt(n)
rate.
With boot_ci_type = "root_calibrated", lpmec() performs a
nested subsampling calibration of the root interval cutoffs. For each
calibration subsample of size m, it treats the full-sample estimate as
a pseudo-truth, builds inner root intervals from smaller subsamples, estimates
candidate one-sided coverage rates, and applies the largest candidate cutoff
whose estimated coverage reaches the nominal target. This is an asymptotic
resampling calibration, not a finite-sample coverage guarantee. Its usual
justification relies on scale separation for the outer and inner subsample
sizes.
With boot_ci_type = "rbc", lpmec() estimates a leading
finite-item-count bias by rerunning the estimator on a fixed, pre-specified
grid of observable-group subsets and fitting each target summary to
a + b / M. It subtracts b / M from the full-M estimate and
constructs root intervals from bootstrap draws of the same bias-corrected
statistic.
A list containing various estimates and statistics (in snake_case):
Naive, IV, corrected IV, and corrected OLS estimates:
ols_*, iv_*, corrected_iv_*, and
corrected_ols_*. Bootstrap uncertainty summaries use suffixes
_se, _lower, _upper, and _tstat where
applicable.
var_est_split and var_est_split_se: Aggregated
split-half measurement-error variance and, when bootstrap draws are
available, its bootstrap standard error.
bayesian_ols_*_outer_normed and
bayesian_ols_*_inner_normed: MCMC coefficient summaries. The
*_parametric standard-error fields retain within-run posterior
uncertainty, while the non-parametric standard-error and interval fields
summarize bootstrap variation.
m_stage_1_erv* and m_reduced_erv*: Extreme robustness
values and bootstrap uncertainty summaries for the first-stage and
reduced-form regressions.
mcmc_joint2_*: NumPyro "mcmc_joint2" diagnostics,
including effective-sample-size percentages, maximum R-hat, divergent
transitions, mean accept probability, and orientation diagnostics.
x_est1 and x_est2: Split-half latent variable
estimates from the original sample.
boot_rbc_diagnostics, boot_rbc_raw_aggregates, and
boot_rbc_pilot_aggregates: Robust-bias-correction diagnostics
returned when boot_ci_type = "rbc".
Intermediary_*: Per-run original-sample and bootstrap
outputs, returned only when return_intermediaries = TRUE.
Jerzak, C. T. and Jessee, S. A. (2025). Attenuation Bias with Latent Predictors. arXiv:2507.22218 [stat.AP]. https://arxiv.org/abs/2507.22218
Calonico, S., Cattaneo, M. D., and Farrell, M. H. (2018). On the Effect of Bias Estimation on Coverage Accuracy in Nonparametric Inference. Journal of the American Statistical Association, 113, 767–779.
# Generate some example data set.seed(123) Y <- rnorm(1000) observables <- as.data.frame(matrix(sample(c(0,1), 1000*10, replace = TRUE), ncol = 10)) # Run the bootstrapped analysis results <- lpmec(Y = Y, observables = observables, n_boot = 10, # small values for illustration only n_partition = 5 # small for size ) # Use a winsorized mean across partitions results_winsorized <- lpmec(Y = Y, observables = observables, n_boot = 10, n_partition = 5, partition_aggregation = "winsorized_mean") # View the corrected IV coefficient and its standard error print(results)# Generate some example data set.seed(123) Y <- rnorm(1000) observables <- as.data.frame(matrix(sample(c(0,1), 1000*10, replace = TRUE), ncol = 10)) # Run the bootstrapped analysis results <- lpmec(Y = Y, observables = observables, n_boot = 10, # small values for illustration only n_partition = 5 # small for size ) # Use a winsorized mean across partitions results_winsorized <- lpmec(Y = Y, observables = observables, n_boot = 10, n_partition = 5, partition_aggregation = "winsorized_mean") # View the corrected IV coefficient and its standard error print(results)
Runs lpmec_moderator_onerun over repeated split-half
partitions (in observables mode) and row (or stratified) bootstrap
samples, re-running the whole pipeline – scoring with fresh splits,
reliability estimation, interaction regression, and correction – on every
(bootstrap, partition) draw so the reported uncertainty reflects all
estimation steps.
lpmec_moderator( Y, treatment, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), boot_basis = seq_along(Y), return_intermediaries = TRUE, estimation_method = "averaging", min_reliability = 0.05, seed = NULL, ... )lpmec_moderator( Y, treatment, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), boot_basis = seq_along(Y), return_intermediaries = TRUE, estimation_method = "averaging", min_reliability = 0.05, seed = NULL, ... )
Y |
Numeric outcome vector with only finite values. |
treatment |
Numeric treatment vector of the same length as |
observables |
Optional list of item matrices or data frames, one per
measure (a single matrix is treated as one measure). Each measure is
scored via |
scores |
Optional named list (or matrix/data frame with one column per measure) of pre-computed full measure scores. Scores are pooled z-scored; split-based reliabilities are unavailable for these measures. |
split_scores |
Optional named list of n x 2 matrices of half scores, one per measure. Each half is pooled z-scored and the full-measure score is the z-score of the mean of the two z-scored halves. |
covariates |
Optional matrix or data frame of observed covariates included additively in the interaction regression. |
n_boot |
Non-negative integer number of n-out-of-n bootstrap
replications. Default |
n_partition |
Positive integer number of fresh split-half partitions
per original or bootstrap sample. Fresh partitions require item-level
inputs, so when |
partition_aggregation |
Aggregation strategy across partitions within
each bootstrap sample; see |
partition_aggregation_probs |
Quantile probabilities for winsorized or trimmed partition aggregation. |
boot_basis |
Optional vector of length |
return_intermediaries |
Logical. If |
estimation_method |
Estimation method(s) passed to
|
min_reliability |
Reliability floor in [0, 1). When
|
seed |
Optional seed applied locally to the partitions and the bootstrap (the caller's random-number state is restored on exit). |
... |
Additional arguments passed to |
The first run (bootstrap index 1) is the original sample; its
partition-aggregated estimates are the reported point estimates, and the
remaining n_boot runs feed the bootstrap standard errors and
percentile intervals. Because reliability estimation is re-done on every
draw, the intervals for corrected_interaction_coef propagate the
sampling uncertainty in rho_half and rho_score – both of
which are reported with their own bootstrap summaries as headline
quantities. Warnings and messages from the pipeline are shown only for
the first (original-sample, first-partition) run; corrected coefficients
floored to NA in bootstrap replications propagate NA
through the default median aggregation.
A list of class lpmec_moderator containing, for each of
treatment_coef, main_coef, interaction_coef,
corrected_main_coef, corrected_interaction_coef,
rho_half, and rho_score: the original-sample estimate
(aggregated across partitions) plus bootstrap _se,
_lower, and _upper summaries (2.5% and 97.5%
percentiles) when n_boot >= 1. Also included are
coef_all/coef_se_all, sb_factor,
per_measure and cor_matrix from the original-sample run,
x_used/x_est/x_est1/x_est2,
measure_names, n_measures, measure_source,
covariate_names, n_obs, n_boot,
n_partition, min_reliability, and – when
return_intermediaries = TRUE – Intermediary_BootIndex,
Intermediary_PartitionIndex, and per-run
Intermediary_* vectors (plus Intermediary_coef_all).
set.seed(101) n <- 400 X <- rnorm(n) treatment <- rbinom(n, 1, 0.5) Y <- 0.2 * treatment + 0.2 * X + 0.3 * treatment * X + rnorm(n) items <- matrix(rbinom(n * 4L, 1, stats::pnorm(outer(X, c(1.2, 1, 0.8, 1.1)) - 0.2)), n, 4L) colnames(items) <- paste0("item", 1:4) result <- lpmec_moderator( Y = Y, treatment = treatment, observables = items, estimation_method = "averaging", n_boot = 4L, n_partition = 2L, seed = 7 ) c(corrected = result$corrected_interaction_coef, lower = result$corrected_interaction_lower, upper = result$corrected_interaction_upper)set.seed(101) n <- 400 X <- rnorm(n) treatment <- rbinom(n, 1, 0.5) Y <- 0.2 * treatment + 0.2 * X + 0.3 * treatment * X + rnorm(n) items <- matrix(rbinom(n * 4L, 1, stats::pnorm(outer(X, c(1.2, 1, 0.8, 1.1)) - 0.2)), n, 4L) colnames(items) <- paste0("item", 1:4) result <- lpmec_moderator( Y = Y, treatment = treatment, observables = items, estimation_method = "averaging", n_boot = 4L, n_partition = 2L, seed = 7 ) c(corrected = result$corrected_interaction_coef, lower = result$corrected_interaction_lower, upper = result$corrected_interaction_upper)
Estimates the interaction between a treatment and a latent moderator that
is measured with error, and corrects the naive interaction coefficient for
the attenuation induced by the moderator score's reliability. With a
randomized treatment and a standardized moderator score x of
reliability rho, the naive interaction coefficient from
Y ~ treatment * x converges to b_TX * sqrt(rho); the
corrected estimate divides by sqrt(rho_score), where
rho_score is the Spearman-Brown as-used reliability of the score
actually entered in the regression.
lpmec_moderator_onerun( Y, treatment, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, estimation_method = "averaging", min_reliability = 0.05, ... )lpmec_moderator_onerun( Y, treatment, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, estimation_method = "averaging", min_reliability = 0.05, ... )
Y |
Numeric outcome vector with only finite values. |
treatment |
Numeric treatment vector of the same length as |
observables |
Optional list of item matrices or data frames, one per
measure (a single matrix is treated as one measure). Each measure is
scored via |
scores |
Optional named list (or matrix/data frame with one column per measure) of pre-computed full measure scores. Scores are pooled z-scored; split-based reliabilities are unavailable for these measures. |
split_scores |
Optional named list of n x 2 matrices of half scores, one per measure. Each half is pooled z-scored and the full-measure score is the z-score of the mean of the two z-scored halves. |
covariates |
Optional matrix or data frame of observed covariates included additively in the interaction regression. |
estimation_method |
Estimation method(s) passed to
|
min_reliability |
Reliability floor in [0, 1). When
|
... |
Additional arguments passed to |
The correction divides by the square root of the reliability of the score
actually used as the regressor (Proposition 6 of the accompanying working
paper). With a single item battery, the split-half correlation
rho_half estimates the reliability of a half score, so the
full-battery score reliability is the Spearman-Brown step-up
2 * rho_half / (1 + rho_half); dividing by sqrt(rho_half)
instead would overcorrect. With M >= 2 measures, the regressor is
the mean of the M aligned z-scored measure scores and the analogous
generalized step-up M * rbar / (1 + (M - 1) * rbar) is applied to
the mean pairwise correlation rbar. When M >= 3, the
per-measure triad reliabilities rho*_m = r_ml * r_mk / r_lk –
consistent when measurement errors are independent across measures –
provide an alternative correction reported in per_measure.
Covariates enter the regression additively; the correction is exact when
the covariates are independent of the latent moderator and approximate
otherwise. Reliabilities below min_reliability (or not estimable,
as with a single scores-mode measure) yield NA corrected
coefficients and a single warning.
A list of class lpmec_moderator_onerun containing:
treatment_coef/treatment_se,
main_coef/main_se,
interaction_coef/interaction_se: naive OLS coefficients
and classical standard errors from
Y ~ treatment + x + treatment:x (plus covariates), where
x is the moderator score in x_used.
coef_all, se_all: all named coefficients (intercept
omitted), including covariates.
rho_half: with one measure, the split-half correlation of
that measure's two half scores; with M >= 2 measures, the mean
pairwise correlation among the z-scored, sign-aligned measure scores.
sb_factor, rho_score: the Spearman-Brown step-up
factor (2 for half scores of one battery, M for M
averaged measures) and the as-used score reliability
rho_score = sb_factor * rho_half / (1 + (sb_factor - 1) *
rho_half).
correction_factor: sqrt(rho_score) when usable,
otherwise NA.
corrected_interaction_coef, corrected_main_coef:
interaction_coef / sqrt(rho_score) and
main_coef / sqrt(rho_score) (NA when rho_score is
below min_reliability or not finite).
reliability_floored: logical, TRUE when the
headline correction was floored to NA.
per_measure: when M >= 3, a data frame with one row
per measure holding the naive per-measure interaction coefficient (and
classical standard error), the pooled triad reliability
rho*_m, and the triad-corrected interaction coefficient;
NULL otherwise.
cor_matrix: pooled cross-measure correlation matrix
(NULL when M == 1).
x_used: the moderator score entered in the regression (the
z-scored full-battery score for one measure; the z-scored mean of the
aligned z-scored measure scores for M >= 2).
x_est, x_est1, x_est2: per-measure pooled
z-scored, sign-aligned score matrices (halves are NA for
scores-mode measures).
measure_names, n_measures, measure_source,
sign_flipped, covariate_names, n_obs,
n_obs_used, min_reliability, scalar_runs.
set.seed(100) n <- 600 X <- rnorm(n) treatment <- rbinom(n, 1, 0.5) Y <- 0.2 * treatment + 0.2 * X + 0.3 * treatment * X + rnorm(n) items <- matrix(rbinom(n * 4L, 1, stats::pnorm(outer(X, c(1.2, 1, 0.8, 1.1)) - 0.2)), n, 4L) colnames(items) <- paste0("item", 1:4) run <- lpmec_moderator_onerun( Y = Y, treatment = treatment, observables = items, estimation_method = "averaging" ) c(naive = run$interaction_coef, rho_score = run$rho_score, corrected = run$corrected_interaction_coef)set.seed(100) n <- 600 X <- rnorm(n) treatment <- rbinom(n, 1, 0.5) Y <- 0.2 * treatment + 0.2 * X + 0.3 * treatment * X + rnorm(n) items <- matrix(rbinom(n * 4L, 1, stats::pnorm(outer(X, c(1.2, 1, 0.8, 1.1)) - 0.2)), n, 4L) colnames(items) <- paste0("item", 1:4) run <- lpmec_moderator_onerun( Y = Y, treatment = treatment, observables = items, estimation_method = "averaging" ) c(naive = run$interaction_coef, rho_score = run$rho_score, corrected = run$corrected_interaction_coef)
Runs lpmec_multivariate_onerun over repeated split-half
partitions and optional row bootstrap samples.
lpmec_multivariate( Y, observables, covariates = NULL, observables_groupings = NULL, make_observables_groupings = FALSE, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), boot_basis = seq_along(Y), return_intermediaries = TRUE, estimation_method = "em", latent_estimation_fn = NULL, ordinal = FALSE, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", anchor_parameter_id = NULL, n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), min_split_correlation = 0, conda_env = "lpmec", conda_env_required = FALSE )lpmec_multivariate( Y, observables, covariates = NULL, observables_groupings = NULL, make_observables_groupings = FALSE, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), boot_basis = seq_along(Y), return_intermediaries = TRUE, estimation_method = "em", latent_estimation_fn = NULL, ordinal = FALSE, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", anchor_parameter_id = NULL, n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), min_split_correlation = 0, conda_env = "lpmec", conda_env_required = FALSE )
Y |
Numeric outcome vector. |
observables |
A list of matrices or data frames, one per latent predictor. |
covariates |
Optional matrix or data frame of observed covariates. |
observables_groupings |
Optional list of grouping vectors, one per latent predictor. Defaults to the column names of each observable matrix. |
make_observables_groupings |
Logical scalar or vector passed to
|
n_boot |
Non-negative integer number of row-bootstrap iterations. |
n_partition |
Positive integer number of split-half partitions per original or bootstrap sample. |
partition_aggregation |
Aggregation strategy across partitions. See
|
partition_aggregation_probs |
Quantile probabilities for winsorized or trimmed partition aggregation. |
boot_basis |
Optional vector of indices or strata for row bootstrap. |
return_intermediaries |
Logical. If |
estimation_method |
Character scalar or vector passed to
|
latent_estimation_fn |
Optional function or list of functions used when
|
ordinal |
Logical scalar or vector passed to |
mcmc_control |
List passed to |
min_split_correlation |
Minimum allowed split-half correlation. The correction is defined only for positive componentwise correlations. |
conda_env |
Character string naming the conda environment for MCMC methods. |
conda_env_required |
Logical indicating whether |
A list of class lpmec_multivariate containing aggregated
uncorrected OLS and corrected IV latent coefficients with bootstrap
uncertainty summaries when n_boot >= 1.
Implements the split-indicator multivariate IV correction for several latent predictors. Each latent predictor is estimated from its own indicator matrix.
lpmec_multivariate_onerun( Y, observables, covariates = NULL, observables_groupings = NULL, make_observables_groupings = FALSE, estimation_method = "em", latent_estimation_fn = NULL, ordinal = FALSE, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", anchor_parameter_id = NULL, n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), min_split_correlation = 0, conda_env = "lpmec", conda_env_required = FALSE )lpmec_multivariate_onerun( Y, observables, covariates = NULL, observables_groupings = NULL, make_observables_groupings = FALSE, estimation_method = "em", latent_estimation_fn = NULL, ordinal = FALSE, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", anchor_parameter_id = NULL, n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), min_split_correlation = 0, conda_env = "lpmec", conda_env_required = FALSE )
Y |
Numeric outcome vector. |
observables |
A list of matrices or data frames, one per latent predictor. |
covariates |
Optional matrix or data frame of observed covariates. |
observables_groupings |
Optional list of grouping vectors, one per latent predictor. Defaults to the column names of each observable matrix. |
make_observables_groupings |
Logical scalar or vector passed to
|
estimation_method |
Character scalar or vector passed to
|
latent_estimation_fn |
Optional function or list of functions used when
|
ordinal |
Logical scalar or vector passed to |
mcmc_control |
List passed to |
min_split_correlation |
Minimum allowed split-half correlation. The correction is defined only for positive componentwise correlations. |
conda_env |
Character string naming the conda environment for MCMC methods. |
conda_env_required |
Logical indicating whether |
A list of class lpmec_multivariate_onerun containing
uncorrected OLS coefficients, uncorrected IV coefficients, corrected IV
coefficients, split-half correlations, first-stage diagnostics, and latent
score matrices.
Implements analysis for latent variable models with measurement error correction
lpmec_onerun( Y, observables, observables_groupings = colnames(observables), make_observables_groupings = FALSE, estimation_method = "em", latent_estimation_fn = NULL, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), ordinal = FALSE, conda_env = "lpmec", conda_env_required = FALSE, partition = NULL, partition_id = NULL )lpmec_onerun( Y, observables, observables_groupings = colnames(observables), make_observables_groupings = FALSE, estimation_method = "em", latent_estimation_fn = NULL, mcmc_control = list(backend = "pscl", n_samples_warmup = 500L, n_samples_mcmc = 1000L, batch_size = 512L, chain_method = "parallel", subsample_method = "full", n_thin_by = 1L, n_chains = 2L, outcome_prior = list(calibration = "data"), joint2_prior = list()), ordinal = FALSE, conda_env = "lpmec", conda_env_required = FALSE, partition = NULL, partition_id = NULL )
Y |
A vector of observed outcome variables |
observables |
A matrix of observable indicators used to estimate the latent variable |
observables_groupings |
A vector specifying groupings for the observable indicators. Default is column names of observables. |
make_observables_groupings |
Logical. If TRUE, creates dummy variables for each level of the observable indicators. Default is FALSE. |
estimation_method |
Character specifying the estimation approach. Options include:
|
latent_estimation_fn |
Custom function for estimating latent trait from |
mcmc_control |
A list indicating parameter specifications if MCMC used.
|
ordinal |
Logical indicating whether the observable indicators are ordinal (TRUE) or binary (FALSE). |
conda_env |
A character string specifying the name of the conda environment to use
via |
conda_env_required |
A logical indicating whether the specified conda environment
must be strictly used. If |
partition |
Optional fixed split-half partition. When supplied, must be
a list with |
partition_id |
Optional identifier for |
This function implements a latent variable analysis with measurement error correction. It splits the observable indicators into two sets, estimates latent variables using each set, and then applies various correction methods including OLS correction and instrumental variable approaches.
A list containing various estimates and statistics:
Naive, IV, corrected IV, and corrected OLS estimates:
ols_*, iv_*, corrected_iv_*, and
corrected_ols_*. Split-specific estimates use suffixes
_a and _b.
var_est_split: Estimated split-half measurement-error
variance.
bayesian_ols_*_outer_normed and
bayesian_ols_*_inner_normed: MCMC coefficient summaries when an
MCMC method is used; otherwise NA.
m_stage_1_erv and m_reduced_erv: Extreme robustness
values for the first-stage and reduced-form regressions.
outcome_prior_*: Resolved outcome-prior values used by
NumPyro joint outcome models.
mcmc_joint2_*: NumPyro "mcmc_joint2" diagnostics,
including effective-sample-size percentages, maximum R-hat, divergent
transitions, mean accept probability, and orientation diagnostics.
x_est1 and x_est2: Split-half latent variable
estimates.
The following single-run standard errors and t-statistics are currently
returned as NA because their analytical derivation is not yet
implemented:
corrected_iv_se: Standard error for the corrected IV
coefficient
corrected_ols_se: Standard error for the corrected OLS coefficient
corrected_ols_tstat: T-statistic for the corrected OLS coefficient
corrected_ols_coef_alt: Alternative corrected OLS coefficient
For inference on these quantities, use the bootstrap approach via lpmec, which
provides valid confidence intervals and standard errors through resampling.
# Generate some example data set.seed(123) Y <- rnorm(1000) observables <- as.data.frame(matrix(sample(c(0,1), 1000*10, replace = TRUE), ncol = 10)) # Run the analysis results <- lpmec_onerun(Y = Y, observables = observables) # View the corrected estimates print(results)# Generate some example data set.seed(123) Y <- rnorm(1000) observables <- as.data.frame(matrix(sample(c(0,1), 1000*10, replace = TRUE), ncol = 10)) # Run the analysis results <- lpmec_onerun(Y = Y, observables = observables) # View the corrected estimates print(results)
Runs lpmec_panel_onerun on the original sample and on
cluster (unit) bootstrap resamples, optionally over repeated split-half
partitions for observables-mode measures, and aggregates the
naive, corrected, and reliability quantities across runs. Units are
resampled with replacement and each draw receives a fresh pseudo-id, so a
unit drawn twice enters as two distinct clusters/fixed-effect groups; the
whole pipeline (scoring, sign alignment, transforms, reliabilities,
regressions, corrections) is re-run on every (bootstrap, partition) pair.
lpmec_panel( Y = NULL, unit = NULL, time = NULL, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, Y_split_scores = NULL, design = c("within", "twoway", "difference", "pooled"), diff_k = 1L, estimation_method = "averaging", min_reliability = 0.05, min_cor_n = 30L, demean_iterations = 25L, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), return_intermediaries = TRUE, seed = NULL, ... )lpmec_panel( Y = NULL, unit = NULL, time = NULL, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, Y_split_scores = NULL, design = c("within", "twoway", "difference", "pooled"), diff_k = 1L, estimation_method = "averaging", min_reliability = 0.05, min_cor_n = 30L, demean_iterations = 25L, n_boot = 32L, n_partition = 10L, partition_aggregation = "median", partition_aggregation_probs = c(0.01, 0.99), return_intermediaries = TRUE, seed = NULL, ... )
Y |
Numeric outcome vector (one value per panel row). Non-finite
values are treated as missing. Optional when |
unit |
Vector of unit (cluster) identifiers, one per row. Required
for the |
time |
Optional numeric vector of time identifiers, one per row.
Required for the |
observables |
Optional list of item matrices or data frames, one per
measure (a single matrix is treated as one measure). Each measure is
scored via |
scores |
Optional named list (or matrix/data frame with one column per measure) of pre-computed full measure scores. |
split_scores |
Optional named list of n x 2 matrices of half scores, one per measure. |
covariates |
Optional matrix or data frame of observed covariates; they are design-transformed together with the outcome and scores and enter both the OLS and both IV stages. Values must be finite. |
Y_split_scores |
Optional n x 2 matrix of outcome half scores for a
latent outcome (Proposition 4). Each half is pooled z-scored;
the outcome reliability |
design |
Panel design transform for estimation: one of
|
diff_k |
Positive integer gap for the |
estimation_method |
Estimation method(s) passed to
|
min_reliability |
Reliability floor for the corrected-OLS division.
Estimated reliabilities below this value (or negative) yield |
min_cor_n |
Minimum number of complete pairs required to report any
correlation. Default |
demean_iterations |
Number of iterated demeaning passes for the
|
n_boot |
Non-negative integer number of cluster-bootstrap
replications. Default |
n_partition |
Positive integer number of split-half partitions per
original or bootstrap sample. Partitions only vary for
|
partition_aggregation |
Aggregation strategy across partitions
within each bootstrap replication: |
partition_aggregation_probs |
Quantile probabilities for winsorized or trimmed partition aggregation. |
return_intermediaries |
Logical. If |
seed |
Optional seed applied locally to the scoring partitions and the bootstrap (the caller's random-number state is restored on exit). |
... |
Additional arguments passed to |
Aggregation follows the package convention: per-run values are first
aggregated across partitions within each bootstrap replication
(partition_aggregation), then the original-sample aggregate is
the point estimate and the bootstrap aggregates provide the standard
error and percentile interval. Bootstrap replications that fail are
caught, recorded as NA rows, counted in boot_n_failed, and
excluded from the bootstrap summaries.
See lpmec_panel_onerun for the correction algebra,
including the "IV multiplies, OLS divides" asymmetry and the covariate
caveat.
A list of class lpmec_panel. For each aggregated quantity
<field> of lpmec_panel_onerun – ols_coef,
corrected_ols_coef(_split/_triad/_pair),
corrected_ols_lower/upper, sd_design_x,
ols_coef_local,
corrected_ols_coef_local(_split/_triad/_pair),
corrected_ols_local_lower/upper, iv_coef,
corrected_iv_coef(_within/_cross), split_correlation,
design_split_correlation, split_rho_score,
design_split_rho_score, triad, design_triad,
pair_correlation, design_pair_correlation,
rho_Y_half, rho_Y,
first_stage_fstat, cross_iv_coef,
corrected_cross_iv_coef, corrected_cross_iv_pair – the
result holds the original-sample partition-aggregated estimate
<field> plus bootstrap <field>_se, <field>_lower,
and <field>_upper (percentile 2.5%/97.5%). Also included:
ols_cluster_se (analytic cluster-robust SE from the original
sample), the original-sample reliability table,
cor_matrices, cor_n_matrices, x_est, x_est1,
x_est2, corrected_ols_source,
corrected_ols_local_source, corrected_iv_source,
metadata (measure_names, n_measures, design,
diff_k, n_obs, n_units, n_boot,
n_partition, boot_n_failed), and – when
return_intermediaries = TRUE – Intermediary_BootIndex,
Intermediary_PartitionIndex, and one Intermediary_<field>
matrix of per-run values (rows ordered as the runs; bootstrap runs that
failed are NA rows).
set.seed(100) n_units <- 60 n_periods <- 12 unit <- rep(seq_len(n_units), times = n_periods) time <- rep(seq_len(n_periods), each = n_units) latent <- rnorm(n_units)[unit] + rnorm(n_units * n_periods, sd = 0.7) half1 <- latent + rnorm(n_units * n_periods, sd = 0.5) half2 <- latent + rnorm(n_units * n_periods, sd = 0.5) Y <- 0.4 * latent + rnorm(n_units)[unit] + rnorm(n_units * n_periods) result <- lpmec_panel( Y = Y, unit = unit, time = time, split_scores = list(m1 = cbind(half1, half2)), design = "within", n_boot = 4L, seed = 1 ) result$corrected_ols_coef result$corrected_ols_coef_seset.seed(100) n_units <- 60 n_periods <- 12 unit <- rep(seq_len(n_units), times = n_periods) time <- rep(seq_len(n_periods), each = n_units) latent <- rnorm(n_units)[unit] + rnorm(n_units * n_periods, sd = 0.7) half1 <- latent + rnorm(n_units * n_periods, sd = 0.5) half2 <- latent + rnorm(n_units * n_periods, sd = 0.5) Y <- 0.4 * latent + rnorm(n_units)[unit] + rnorm(n_units * n_periods) result <- lpmec_panel( Y = Y, unit = unit, time = time, split_scores = list(m1 = cbind(half1, half2)), design = "within", n_boot = 4L, seed = 1 ) result$corrected_ols_coef result$corrected_ols_coef_se
Estimates the effect of a latent predictor on a panel outcome under a
fixed-effects or differencing design, and corrects the naive coefficient
for the design-amplified attenuation caused by measurement error in the
latent-variable scores (Propositions 1, 3, and 7 of the accompanying
working paper; Proposition 2a for the design-local scale and
Proposition 4 for latent outcomes). Latent measures may be supplied as
raw item batteries (observables, scored via
lpmec_onerun), as pre-computed half scores
(split_scores), or as full pre-computed scores (scores);
the three sources are merged by measure name.
lpmec_panel_onerun( Y = NULL, unit = NULL, time = NULL, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, Y_split_scores = NULL, design = c("within", "twoway", "difference", "pooled"), diff_k = 1L, estimation_method = "averaging", min_reliability = 0.05, min_cor_n = 30L, demean_iterations = 25L, partition = NULL, ... )lpmec_panel_onerun( Y = NULL, unit = NULL, time = NULL, observables = NULL, scores = NULL, split_scores = NULL, covariates = NULL, Y_split_scores = NULL, design = c("within", "twoway", "difference", "pooled"), diff_k = 1L, estimation_method = "averaging", min_reliability = 0.05, min_cor_n = 30L, demean_iterations = 25L, partition = NULL, ... )
Y |
Numeric outcome vector (one value per panel row). Non-finite
values are treated as missing. Optional when |
unit |
Vector of unit (cluster) identifiers, one per row. Required
for the |
time |
Optional numeric vector of time identifiers, one per row.
Required for the |
observables |
Optional list of item matrices or data frames, one per
measure (a single matrix is treated as one measure). Each measure is
scored via |
scores |
Optional named list (or matrix/data frame with one column per measure) of pre-computed full measure scores. |
split_scores |
Optional named list of n x 2 matrices of half scores, one per measure. |
covariates |
Optional matrix or data frame of observed covariates; they are design-transformed together with the outcome and scores and enter both the OLS and both IV stages. Values must be finite. |
Y_split_scores |
Optional n x 2 matrix of outcome half scores for a
latent outcome (Proposition 4). Each half is pooled z-scored;
the outcome reliability |
design |
Panel design transform for estimation: one of
|
diff_k |
Positive integer gap for the |
estimation_method |
Estimation method(s) passed to
|
min_reliability |
Reliability floor for the corrected-OLS division.
Estimated reliabilities below this value (or negative) yield |
min_cor_n |
Minimum number of complete pairs required to report any
correlation. Default |
demean_iterations |
Number of iterated demeaning passes for the
|
partition |
Optional named list of fixed split-half partitions,
keyed by measure name, passed to |
... |
Additional arguments passed to |
Under the panel design transform, classical measurement error attenuates
the naive coefficient by the design reliability rho_design of the
(pooled-standardized) score, while the pooled standardization inflates it
by 1 / sqrt(rho_pooled), so
plim b = beta * sqrt(rho_pooled) * rho_design / rho_pooled
simplifies to beta * rho_design / sqrt(rho_pooled) and the
corrected OLS coefficient is b * sqrt(rho_pooled) / rho_design.
Fixed-effects and differencing transforms strip the persistent part of
the latent signal but not the transient measurement error, so
rho_design is typically far below rho_pooled and pooled
corrections badly understate the bias.
Score-scale matching (Assumption 3). The reliabilities entering
the OLS division must be those of the score actually regressed. The raw
half-split correlation estimates the reliability of a half score,
while the regression uses the full score (the average of the two z-scored
halves, or the full-battery estimate), so the split-based correction uses
the Spearman-Brown step-up 2r / (1 + r) of both the pooled and the
design split correlations. The step-up is exact when the full score is
the average of two independent parallel halves and a parallel-forms
approximation for full-battery estimates. When a measure merges a
user-supplied full score with separate half scores
(scores + split_scores), the stepped-up value matches the
supplied score's error covariance only under that same parallel-forms
assumption, so the split-based correction is then a sensitivity
calculation.
IV multiplies, OLS divides. The corrected OLS coefficient
divides by the design reliability, which is estimated with noise and can
be near zero under aggressive transforms; corrections with
rho_design < min_reliability (or with the pooled reliability below
the floor) are therefore reported as NA rather than divided out.
The split-IV correction instead multiplies the design-transformed IV
coefficient by sqrt(rho_pooled): the instrument (the other half
score or another measure) removes the design-reliability denominator, so
the corrected IV estimate stays stable exactly where the OLS correction
becomes fragile. Do not swap the two operations.
Reliability variants for the OLS correction: the Spearman-Brown
stepped-up within-measure split reliability (exceeds construct-relevant
reliability when the halves share systematic error, Proposition 7a), the
cross-measure triad r_ml * r_mk / r_lk (requires 3+ measures;
consistent under pairwise-orthogonal total errors, Proposition 7b, and a
lower bound only under the target-specific ratio condition of
Proposition 7c – shared error can move it in either direction), and –
only for a two-measure system where a measure has no split halves – the
cross-measure pair correlation, which identifies the common reliability
under a parallel-measures assumption. corrected_ols_lower and
corrected_ols_upper span the finite variants; this is a
sensitivity range, not a partial-identification interval, unless the
corresponding Proposition 7 condition is maintained.
Covariate caveat. With covariates, the scalar OLS correction is exact only when the covariates are uncorrelated with the latent predictor; otherwise the measurement error also contaminates the covariate coefficients and the correction of the latent slope is approximate. The split-IV estimator remains consistent for the latent slope in the presence of exogenous covariates, which enter both stages.
A list of class lpmec_panel_onerun containing, with one
named entry per measure unless noted:
ols_coef, ols_se, ols_n_obs,
ols_n_clusters: naive design-transformed OLS coefficient of
Y on the measure score with cluster-robust (by unit) standard
error.
corrected_ols_coef, corrected_ols_coef_split,
corrected_ols_coef_triad, corrected_ols_coef_pair,
corrected_ols_lower, corrected_ols_upper,
corrected_ols_source: corrected OLS coefficient(s)
b * sqrt(rho_pooled) / rho_design per reliability variant
(the split variant uses the Spearman-Brown stepped-up reliabilities
split_rho_score/design_split_rho_score), the headline
value (split when available, else triad, else the two-measure
parallel pair), and the [min, max] sensitivity range over the finite
variants.
sd_design_x, ols_coef_local,
corrected_ols_coef_local(_split/_triad/_pair),
corrected_ols_local_lower/_upper,
corrected_ols_local_source: design-local-scale quantities
(Proposition 2a): the sd of the design-transformed score on the
estimation sample, the naive local slope
ols_coef * sd_design_x (effect per SD of the
transformed latent trait), and its corrections
ols_coef_local / sqrt(rho_design) per design-scale
reliability variant. The local estimand moves with the design and is
not comparable across specifications.
split_correlation, design_split_correlation,
split_rho_score, design_split_rho_score, triad,
design_triad, pair_correlation,
design_pair_correlation: reliability estimates under the
pooled and estimation designs; *_rho_score are the
Spearman-Brown step-ups of the raw half-split correlations to the
full-score scale.
rho_Y_half, rho_Y: with Y_split_scores, the
raw outcome half-score correlation and its Spearman-Brown step-up
(NA for an observed outcome).
iv_coef_a, iv_coef_b, iv_coef,
iv_se_a, iv_se_b, first_stage_fstat_a,
first_stage_fstat_b: within-measure split-IV fits (half 1
instrumented by half 2 and the reverse) on the design-transformed
data, with clustered first-stage F statistics.
corrected_iv_coef_a, corrected_iv_coef_b,
corrected_iv_coef_within: within-measure IV corrected by
sqrt of the pooled split correlation.
cross_iv_coef, cross_iv_se,
cross_first_stage_fstat, corrected_cross_iv_coef
(named "<regressor>_by_<instrument>"),
corrected_cross_iv_pair (direction-averaged, named
"<a>_x_<b>"), corrected_iv_coef_cross (per regressor,
averaged over instruments): cross-measure IV fits with the
target-oriented correction of Proposition 3c – sqrt of the
regressor (target) measure's pooled triad reliability when 3+
measures are supplied, or sqrt of the pooled pair correlation
under the two-measure parallel-measures fallback.
corrected_iv_coef, corrected_iv_source,
first_stage_fstat: headline corrected IV per measure
(within-measure when available, else cross-measure) and the minimum
first-stage F statistic among the directions it averages.
reliability: data frame with one row per (design, measure)
holding split_correlation, split_n, rho_split,
triad, rho_lo, rho_hi (the Proposition-7
sensitivity range).
cor_matrices, cor_n_matrices: per-design
cross-measure correlation matrices and complete-pair counts.
x_est, x_est1, x_est2: pooled z-scored,
sign-aligned measure scores and half scores; scalar_runs: the
underlying lpmec_onerun fits for
observables-mode measures.
Metadata: measure_names, n_measures,
measure_source, has_splits, sign_flipped,
covariate_names, design, diff_k, n_obs,
n_units, min_reliability, min_cor_n,
demean_iterations.
set.seed(100) n_units <- 60 n_periods <- 12 unit <- rep(seq_len(n_units), times = n_periods) time <- rep(seq_len(n_periods), each = n_units) latent <- rnorm(n_units)[unit] + rnorm(n_units * n_periods, sd = 0.7) half1 <- latent + rnorm(n_units * n_periods, sd = 0.5) half2 <- latent + rnorm(n_units * n_periods, sd = 0.5) Y <- 0.4 * latent + rnorm(n_units)[unit] + rnorm(n_units * n_periods) run <- lpmec_panel_onerun( Y = Y, unit = unit, time = time, split_scores = list(m1 = cbind(half1, half2)), design = "within" ) run$ols_coef run$corrected_ols_coef run$corrected_iv_coefset.seed(100) n_units <- 60 n_periods <- 12 unit <- rep(seq_len(n_units), times = n_periods) time <- rep(seq_len(n_periods), each = n_units) latent <- rnorm(n_units)[unit] + rnorm(n_units * n_periods, sd = 0.7) half1 <- latent + rnorm(n_units * n_periods, sd = 0.5) half2 <- latent + rnorm(n_units * n_periods, sd = 0.5) Y <- 0.4 * latent + rnorm(n_units)[unit] + rnorm(n_units * n_periods) run <- lpmec_panel_onerun( Y = Y, unit = unit, time = time, split_scores = list(m1 = cbind(half1, half2)), design = "within" ) run$ols_coef run$corrected_ols_coef run$corrected_iv_coef
Estimates, for each latent measure and each requested design transform,
the within-measure split correlation (with its Spearman-Brown step-up to
the full-score scale, rho_split) and the cross-measure triad
reliability, and reports the sensitivity range
[rho_lo, rho_hi] spanned by the two candidates for the measure's
design reliability (Proposition 7 of the accompanying working paper).
The range is a sensitivity diagnostic, not a partial-identification
interval, unless Proposition 7's corresponding orthogonality or ratio
condition is maintained. Optionally attaches a cluster (unit) bootstrap
for all reported reliability quantities.
lpmec_reliability_bounds( observables = NULL, scores = NULL, split_scores = NULL, unit = NULL, time = NULL, designs = "pooled", diff_k = 1L, estimation_method = "averaging", min_reliability = 0.05, min_cor_n = 30L, demean_iterations = 25L, n_boot = 0L, seed = NULL, ... )lpmec_reliability_bounds( observables = NULL, scores = NULL, split_scores = NULL, unit = NULL, time = NULL, designs = "pooled", diff_k = 1L, estimation_method = "averaging", min_reliability = 0.05, min_cor_n = 30L, demean_iterations = 25L, n_boot = 0L, seed = NULL, ... )
observables |
Optional list of item matrices or data frames, one per
measure (a single matrix is treated as one measure). Each measure is
scored via |
scores |
Optional named list (or matrix/data frame with one column per measure) of pre-computed full measure scores. Scores are pooled z-scored; split-based quantities are unavailable for these measures. |
split_scores |
Optional named list of n x 2 matrices of half scores, one per measure. Each half is pooled z-scored and the full-measure score is the z-score of the mean of the two z-scored halves. This is the required input mode for measures with only 2 components. |
unit |
Optional vector of unit (cluster) identifiers, one per row.
Required for the |
time |
Optional numeric vector of time identifiers, one per row.
Required for the |
designs |
Character vector of design transforms; any of
|
diff_k |
Positive integer gap for the |
estimation_method |
Estimation method(s) passed to
|
min_reliability |
Reliability floor. Estimated reliabilities below
this value (or negative) are excluded from the bounds and reported as
|
min_cor_n |
Minimum number of complete pairs required to report any
correlation; correlations on fewer pairs are |
demean_iterations |
Number of iterated demeaning passes for the
|
n_boot |
Non-negative integer number of cluster-bootstrap
replications. Units are resampled with replacement and receive fresh
pseudo-ids (a unit drawn twice enters as two distinct clusters); the
whole pipeline (scoring, sign alignment, transforms, reliabilities,
bounds) is re-run on each draw. Default |
seed |
Optional seed applied locally to the scoring partitions and the bootstrap (the caller's random-number state is restored on exit). |
... |
Additional arguments passed to |
The split correlation between two half scores of the same measure
consistently estimates the reliability of a half score;
rho_split = 2r/(1+r) steps it up to the scale of the full score
(exact when the full score is the average of two independent parallel
halves, a parallel-forms approximation otherwise). The two candidates
entering the range therefore both target the full score's reliability.
Their directional interpretation is model-dependent (Proposition 7):
when the halves share a common systematic error component orthogonal to
the trait, the split-based value exceeds construct-relevant reliability
(Prop 7a); the triad rho*_m = r_ml * r_mk / r_lk equals it exactly
when the measures' total errors are pairwise orthogonal (Prop 7b) and is
a lower bound only under the target-specific ratio condition of Prop 7c
– shared error among the other two measures pushes it down, but shared
error involving the target measure can push it up. Absent those
conditions, [rho_lo, rho_hi] is the [min, max] of two sensitivity
candidates, not an identified set. With fewer than 3 measures the triad
is not available and both endpoints collapse to rho_split.
Correlations are computed after pooled z-scoring and sign alignment of
all measure scores; correlations with fewer than min_cor_n
complete pairs, and reliabilities below min_reliability, are
reported as NA rather than propagated into unstable divisions.
A list of class lpmec_reliability_bounds containing:
reliability: data frame with one row per (design, measure)
holding split_correlation, split_n, rho_split
(the Spearman-Brown step-up of the split correlation to the
full-score scale), triad, rho_lo, rho_hi, and –
when n_boot > 0 – bootstrap _se, _lower, and
_upper columns for each of these reliability quantities.
cor_matrices and cor_n_matrices: per-design
cross-measure correlation matrices and complete-pair counts.
x_est, x_est1, x_est2: pooled z-scored,
sign-aligned measure score matrices (halves are NA for
scores-mode measures).
measure_names, n_measures, designs,
measure_source, sign_flipped, n_obs,
n_units, diff_k, demean_iterations,
min_reliability, min_cor_n, n_boot,
n_boot_failed.
When n_boot > 0: Intermediary_BootIndex and
per-replication matrices Intermediary_split_correlation,
Intermediary_rho_split, Intermediary_triad,
Intermediary_rho_lo, Intermediary_rho_hi (row 1 is the
original sample).
set.seed(100) n <- 400 latent <- rnorm(n) half1 <- latent + rnorm(n, sd = 0.6) half2 <- latent + rnorm(n, sd = 0.6) score2 <- latent + rnorm(n, sd = 0.7) score3 <- latent + rnorm(n, sd = 0.7) bounds <- lpmec_reliability_bounds( split_scores = list(measure1 = cbind(half1, half2)), scores = list(measure2 = score2, measure3 = score3) ) bounds$reliabilityset.seed(100) n <- 400 latent <- rnorm(n) half1 <- latent + rnorm(n, sd = 0.6) half2 <- latent + rnorm(n, sd = 0.6) score2 <- latent + rnorm(n, sd = 0.7) score3 <- latent + rnorm(n, sd = 0.7) bounds <- lpmec_reliability_bounds( split_scores = list(measure1 = cbind(half1, half2)), scores = list(measure2 = score2, measure3 = score3) ) bounds$reliability
Creates visualizations of LPMEC model results. Can plot either the latent variable estimates or the bootstrap distribution of coefficients.
## S3 method for class 'lpmec' plot(x, type = "latent", ...)## S3 method for class 'lpmec' plot(x, type = "latent", ...)
x |
An object of class |
type |
Character string specifying the plot type. Either |
... |
No return value, called for side effects (creates a plot).
lpmec, summary.lpmec, print.lpmec
Creates a scatter plot of the two pooled half scores of the first measure with split halves; when no measure has half scores, falls back to a scatter plot of the first two measure scores.
## S3 method for class 'lpmec_moderator' plot(x, ...)## S3 method for class 'lpmec_moderator' plot(x, ...)
x |
An object of class |
... |
Additional arguments passed to |
No return value, called for side effects (creates a plot).
Creates a scatter plot comparing the two split-half latent variable estimates.
## S3 method for class 'lpmec_onerun' plot(x, ...)## S3 method for class 'lpmec_onerun' plot(x, ...)
x |
An object of class |
... |
Additional arguments passed to |
No return value, called for side effects (creates a plot).
lpmec_onerun, summary.lpmec_onerun, print.lpmec_onerun
Creates a scatter plot of the two pooled half scores of the first measure with split halves; when no measure has half scores, falls back to a scatter plot of the first two measure scores.
## S3 method for class 'lpmec_panel' plot(x, ...)## S3 method for class 'lpmec_panel' plot(x, ...)
x |
An object of class |
... |
Additional arguments passed to |
No return value, called for side effects (creates a plot).
Prints a concise summary of bootstrapped LPMEC model results.
## S3 method for class 'lpmec' print(x, ...)## S3 method for class 'lpmec' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
lpmec, summary.lpmec, plot.lpmec
Print method for lpmec_moderator objects
## S3 method for class 'lpmec_moderator' print(x, ...)## S3 method for class 'lpmec_moderator' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
Print method for lpmec_moderator_onerun objects
## S3 method for class 'lpmec_moderator_onerun' print(x, ...)## S3 method for class 'lpmec_moderator_onerun' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
Print method for lpmec_multivariate objects
## S3 method for class 'lpmec_multivariate' print(x, ...)## S3 method for class 'lpmec_multivariate' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
Print method for lpmec_multivariate_onerun objects
## S3 method for class 'lpmec_multivariate_onerun' print(x, ...)## S3 method for class 'lpmec_multivariate_onerun' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
Prints a concise summary of single-run LPMEC model results.
## S3 method for class 'lpmec_onerun' print(x, ...)## S3 method for class 'lpmec_onerun' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
lpmec_onerun, summary.lpmec_onerun, plot.lpmec_onerun
Print method for lpmec_panel objects
## S3 method for class 'lpmec_panel' print(x, ...)## S3 method for class 'lpmec_panel' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
Print method for lpmec_panel_onerun objects
## S3 method for class 'lpmec_panel_onerun' print(x, ...)## S3 method for class 'lpmec_panel_onerun' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
Print method for lpmec_reliability_bounds objects
## S3 method for class 'lpmec_reliability_bounds' print(x, ...)## S3 method for class 'lpmec_reliability_bounds' print(x, ...)
x |
An object of class |
... |
Additional arguments (currently unused). |
The input object x, returned invisibly.
Provides a comprehensive summary of bootstrapped LPMEC model results including OLS, IV, corrected, and Bayesian coefficient estimates with confidence intervals.
## S3 method for class 'lpmec' summary(object, ...)## S3 method for class 'lpmec' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame containing coefficient estimates, standard errors, and confidence intervals, returned invisibly. The data frame has rows for OLS, IV, Corrected IV, Corrected OLS, and Bayesian OLS estimates.
lpmec, print.lpmec, plot.lpmec
Summary method for lpmec_moderator objects
## S3 method for class 'lpmec_moderator' summary(object, ...)## S3 method for class 'lpmec_moderator' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame of naive and corrected interaction-regression coefficient estimates and reliability quantities with bootstrap standard errors and percentile confidence intervals, returned invisibly.
Summary method for lpmec_moderator_onerun objects
## S3 method for class 'lpmec_moderator_onerun' summary(object, ...)## S3 method for class 'lpmec_moderator_onerun' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame of naive and corrected interaction-regression coefficient estimates, returned invisibly. When three or more measures are supplied, the per-measure triad corrections are also printed.
Summary method for lpmec_multivariate objects
## S3 method for class 'lpmec_multivariate' summary(object, ...)## S3 method for class 'lpmec_multivariate' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame of aggregated latent-predictor coefficient estimates.
Summary method for lpmec_multivariate_onerun objects
## S3 method for class 'lpmec_multivariate_onerun' summary(object, ...)## S3 method for class 'lpmec_multivariate_onerun' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame of latent-predictor coefficient estimates.
Provides a summary of single-run LPMEC model results including OLS, IV, and corrected coefficient estimates.
## S3 method for class 'lpmec_onerun' summary(object, ...)## S3 method for class 'lpmec_onerun' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame containing coefficient estimates and standard errors, returned invisibly. The data frame has rows for OLS, IV, Corrected IV, and Corrected OLS estimates.
lpmec_onerun, print.lpmec_onerun, plot.lpmec_onerun
Summary method for lpmec_panel objects
## S3 method for class 'lpmec_panel' summary(object, ...)## S3 method for class 'lpmec_panel' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame with one row per measure holding the naive OLS coefficient, the headline corrected OLS coefficient with its [min, max] reliability-variant interval, the corrected IV coefficient (with cluster-bootstrap standard errors), the pooled split and triad reliabilities, and the first-stage F statistic, returned invisibly.
Summary method for lpmec_panel_onerun objects
## S3 method for class 'lpmec_panel_onerun' summary(object, ...)## S3 method for class 'lpmec_panel_onerun' summary(object, ...)
object |
An object of class |
... |
Additional arguments (currently unused). |
A data frame with one row per measure holding the naive OLS coefficient (with cluster-robust standard error), the headline corrected OLS coefficient with its [min, max] reliability-variant interval, the corrected IV coefficient, the pooled split and triad reliabilities, and the first-stage F statistic, returned invisibly.