
Kapelner and Krieger's (2014) Sequential "Matching-on-the-Fly" Design
Source:R/design_seq_one_by_one_KK14.R
DesignSeqOneByOneKK14.RdA DesignSeqOneByOne that matches subjects to
each other as they arrive, rather than requiring all subjects up front (as
DesignFixedBinaryMatch does): each new
subject is either matched to its nearest (Mahalanobis-distance) unmatched prior
subject in the "reservoir" — if that distance is small enough to pass a
statistical closeness test — and assigned the opposite treatment from its
match, or, if no sufficiently close match exists (or matching hasn't started yet),
randomized and added to the reservoir for future subjects to potentially match
against.
Burn-in. For the first t_0_pct * n subjects (default 35%), or
whenever no covariates are yet available, subjects are simply randomized
(\(\mathrm{Bernoulli}(prob\_T)\)) and placed in the reservoir (private$m
set to 0 for that subject) — matching does not begin until enough subjects have
accumulated to estimate a stable covariate covariance structure.
Matching test. Once past burn-in, for new subject \(t\) with covariate
vector \(x_t\), the squared Mahalanobis distance (via
compute_proportional_mahal_distances_cpp(), using the sample covariance of
all prior subjects' covariates, ridge-regularized by .Machine$double.eps) to
every subject currently in the reservoir is computed, and the closest one is a
candidate match. The match is accepted only if that squared distance falls
below a threshold \(T^2_{\mathrm{cutoff}}\) derived from an F critical value,
$$T^2_{\mathrm{cutoff}} = \frac{p(n-1)}{n-p} \, F_{p,\, t-p}(\lambda),$$
where \(p\) is the rank of the covariate matrix so far, \(n\) is the design's
target (planned) sample size, \(t\) is the number of subjects enrolled so far, and
\(\lambda\) (lambda, default 0.1) is the F-distribution quantile level —
i.e. this is a
Hotelling's \(T^2\)-type test of whether the candidate pair's covariate
difference is small enough to plausibly be exchangeable "noise" rather than a
meaningful covariate mismatch; lambda controls how strict that test is
(smaller lambda accepts fewer, closer matches). If accepted, both subjects
are recorded as a new match (private$m), and the new subject receives the
opposite treatment of its match, guaranteeing exactly one treated and one
control per matched pair — the same guarantee
DesignFixedBinaryMatch provides, but
formed incrementally rather than all at once. If rejected (or the reservoir is
empty), the subject is randomized and added to the reservoir instead.
Lifecycle note. The morrison and p constructor arguments are
currently recorded on the object but not consulted anywhere in the matching or
assignment logic in this version of the class; treat them as reserved for future use
rather than as active configuration.
References
Kapelner, A., and Krieger, A. M. (2014). "Matching on-the-fly: Sequential allocation with higher power and efficiency." Biometrics, 70(2), 378-388, doi:10.1111/biom.12148 . See also Hotelling's T-squared distribution for the matching-test statistic, and Mahalanobis distance.
Super classes
Design -> DesignSeqOneByOne -> DesignSeqOneByOneKK14
Methods
+ inherited public methods from DesignSeqOneByOne
+ inherited public methods from Design
Design$add_all_subject_responses()Design$add_one_subject_response()Design$any_censoring()Design$applicable_inference_class_names()Design$assert_all_responses_recorded()Design$assert_all_subjects_arrived()Design$assert_even_allocation()Design$assert_fixed_sample()Design$capabilities()Design$check_experiment_completed()Design$draw_ws_according_to_design()Design$duplicate()Design$get_X()Design$get_X_imp()Design$get_X_raw()Design$get_design_formula()Design$get_edi_version_created()Design$get_effective_dead()Design$get_effective_time()Design$get_missingness_method()Design$get_n()Design$get_ordinal_levels()Design$get_original_ordinal_levels()Design$get_prob_T()Design$get_response_type()Design$get_response_type_original()Design$get_t()Design$get_w()Design$get_y()Design$get_y_L()Design$get_y_R()Design$get_y_original()Design$has_general_censoring()Design$incompatible_inference_classes_due_to_design_structure()Design$is_a_bernoulli_capable()Design$is_a_cluster_capable()Design$is_blocking_design()Design$is_fixed_sample_size()Design$is_matching_design()Design$overwrite_all_subject_assignments()Design$prepare_for_resampling_replay()Design$randomization_family()Design$supports()Design$supports_randomization_draw()Design$supports_resampling()Design$supports_resampling_replay()Design$transform_y()Design$unavailable_inference_classes_due_to_missing_packages()Design$warm_all_subject_data_cache()
DesignSeqOneByOneKK14$is_a_kk_matching_capable()
Characterization: this design matches subjects to each other incrementally as they arrive (see class documentation), so it is KK matching-on-the-fly-capable by construction.
DesignSeqOneByOneKK14$new()
Initialize a KK14 sequential matching-on-the-fly experimental design (see class documentation for the burn-in and matching-test rules).
Usage
DesignSeqOneByOneKK14$new(
response_type,
prob_T = 0.5,
include_is_missing_as_a_new_feature = TRUE,
n = NULL,
verbose = FALSE,
lambda = NULL,
t_0_pct = NULL,
morrison = FALSE,
p = NULL,
missingness_method = "impute",
design_formula = ~.,
seed = NULL
)Arguments
response_type"continuous", "incidence", "proportion", "count", "survival", or "ordinal".
prob_TProbability of treatment assignment used for burn-in/ unmatched (reservoir) subjects; matched subjects instead always receive the opposite assignment of their match (see class documentation).
include_is_missing_as_a_new_featureFlag for missingness indicators.
nThe sample size.
verboseA flag for verbosity.
lambdaThe F-distribution quantile level controlling how strict the matching-acceptance test is (default 0.1; smaller values accept fewer, closer matches). See class documentation for the exact threshold formula.
t_0_pctThe fraction of
nsubjects to randomize into the reservoir before matching begins (default 0.35).morrisonCurrently unused by this class's matching/assignment logic; reserved for future use.
pCurrently unused by this class's matching/assignment logic; reserved for future use.
missingness_methodHow to handle missing values in covariates.
design_formulaA formula object.
seedInteger seed for reproducibility.
DesignSeqOneByOneKK14$assign_wt()
Draw the next subject's treatment assignment via KK14 matching-on-the-fly (see class documentation): during burn-in, or if no sufficiently close reservoir match exists, randomize and add the subject to the reservoir; otherwise match to the nearest reservoir subject and assign the opposite treatment.
Examples
seq_des = DesignSeqOneByOneKK14$new(n = 6, response_type = 'continuous')
seq_des$add_one_subject_to_experiment_and_assign(data.frame(x1 = rnorm(1)))
#> [1] 0