
Stepwise Variant of the KK21 Outcome-Weighted Sequential Matching Design
Source:R/design_seq_one_by_one_KK21_stepwise.R
DesignSeqOneByOneKK21stepwise.RdA DesignSeqOneByOneKK21 variant that
computes its per-covariate matching weights via forward stepwise selection
(compute_weights_KK21stepwise()) instead of KK21's independent
marginal-association regressions: covariates are added to a growing "selected" set
one at a time, at each step choosing whichever remaining covariate has the largest
absolute association statistic conditional on (i.e. in a model that also
includes) the covariates already selected and the treatment-assignment column,
rather than each covariate's association with the response considered in isolation.
This targets the case where covariates are mutually correlated: KK21's marginal
weights can assign similar high weight to several collinear prognostic covariates
(effectively double-counting the same information), whereas the stepwise conditional
weights down-weight a covariate once its explanatory content is already captured by
previously selected covariates.
Weight computation. For each response type, a family-appropriate model
(OLS/logistic/negative-binomial/beta/AFT survival/proportional-odds, matching the
same response-type dispatch and *_use_speedup fast-path conventions as
DesignSeqOneByOneKK21) is repeatedly refit,
each time regressing the response on one candidate remaining covariate plus all
previously selected covariates plus the treatment column ws; the candidate
with the largest absolute association statistic is selected next and assigned that
statistic as its weight, then removed from the candidate pool, and the process
repeats until every covariate has been assigned a weight (an \(O(p^2)\) number of
model fits per assignment call, for \(p\) covariates). If a candidate's model fit
fails to converge (e.g. perfect separation or rank deficiency) partway through, the
remaining not-yet-selected covariates' weights are left NA internally and then
replaced with 0 (excluding them from the weighted matching distance) rather than
propagating the failure.
Everything else is inherited from KK21. Burn-in fallback to KK14, the
bootstrapped acceptance-threshold test, matched-pair assignment, and the
morrison/lambda/t_0_pct matching-schedule options are all
unchanged from DesignSeqOneByOneKK21; only
how the covariate weight vector is computed differs.
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
, for the base matching-on-the-fly algorithm; the
outcome-weighted extension follows Kapelner and Krieger (2021), with this class
using a forward-stepwise (rather than marginal) weight-estimation scheme. See also
Morrison, T., and Owen, A. B. (2025) for the alternative morrison = TRUE
threshold calibration referenced by the morrison argument.
Super classes
Design -> DesignSeqOneByOne -> DesignSeqOneByOneKK14 -> DesignSeqOneByOneKK21 -> DesignSeqOneByOneKK21stepwise
Methods
+ inherited public methods from DesignSeqOneByOneKK21
+ inherited public methods from DesignSeqOneByOneKK14
DesignSeqOneByOneKK14$add_all_subject_matched_pair_ids()DesignSeqOneByOneKK14$assert_blocking_design()DesignSeqOneByOneKK14$assert_equal_block_sizes()DesignSeqOneByOneKK14$assert_matching_design()DesignSeqOneByOneKK14$get_block_ids()DesignSeqOneByOneKK14$get_cmh_se_w_mat()DesignSeqOneByOneKK14$get_matching_cluster_ids()DesignSeqOneByOneKK14$inject_cmh_se_w_mat()DesignSeqOneByOneKK14$is_a_kk_matching_capable()DesignSeqOneByOneKK14$is_blocking_design()DesignSeqOneByOneKK14$is_complete_blocking_design()DesignSeqOneByOneKK14$is_matching_design()DesignSeqOneByOneKK14$set_m()DesignSeqOneByOneKK14$summarize_blocks()+ 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_fixed_sample_size()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()
DesignSeqOneByOneKK21stepwise$new()
Initialize a matching-on-the-fly sequential experimental design whose covariate matching weights are computed via forward stepwise selection (see class documentation), based on the stepwise version of Kapelner and Krieger (2021) with option to use matching parameters of Morrison and Owen (2025)
Usage
DesignSeqOneByOneKK21stepwise$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,
num_boot = NULL,
count_use_speedup = TRUE,
proportion_use_speedup = TRUE,
survival_use_speedup_for_no_censoring = TRUE,
ordinal_use_speedup = TRUE,
missingness_method = "impute",
design_formula = ~.,
...
)Arguments
response_typeThe data type of response values which must be one of the following: "continuous", "incidence", "proportion", "count", "survival". This package will enforce that all added responses via the
add_one_subject_responsemethod will be of the appropriate type.prob_TThe probability of the treatment assignment. This defaults to
0.5.include_is_missing_as_a_new_featureIf missing data is present in a variable, should we include another dummy variable for its missingness in addition to imputing its value? If the feature is type factor, instead of creating a new column, we allow missingness to be its own level. The default is
TRUE.nThe sample size (if fixed). Default is
NULLfor not fixed.verboseA flag indicating whether messages should be displayed to the user. Default is
FALSE.lambdaThe quantile cutoff of the subject distance distribution for determining matches. If unspecified and
morrison = FALSE, default is 10%.t_0_pctThe percentage of total sample size n where matching begins. If unspecified and
morrison = FALSE, default is 35%.morrisonDefault is
FALSEwhich implies matching via the KK14 algorithm usinglambdaandt_0_pctmatching. IfTRUE, we use Morrison and Owen (2025)'s formula forlambdawhich differs in the fixed n versus variable n settings and matching begins immediately with no wait for a certain reservoir size like in KK14.pThe number of covariate features. Must be specified when
morrison = TRUEotherwise do not specify this argument.num_bootthe number of bootstrap samples taken to approximate the subject-distance distribution. Default is 500.
count_use_speedupShould we speed up the estimation of the weights in the response = count case via a continuous regression on log(y + 1). instead of a negative binomial regression each time? This is at the expense of the weights being less accurate. Default is
TRUE.proportion_use_speedupShould we speed up the estimation of the weights in the response = proportion case via a continuous regression on log(y / (1 - y)) instead of a beta regression each time? This is at the expense of the weights being less accurate. Default is
TRUE.survival_use_speedup_for_no_censoringShould we speed up the estimation of the weights in the response = survival case via a continuous regression on log(y) instead of a Weibull AFT regression each time, but only when there is no censoring in the data collected so far? This is at the expense of the weights being less accurate when censoring is present. Default is
TRUE.ordinal_use_speedupShould we speed up the estimation of the weights in the response = ordinal case via a continuous regression on the ordinal levels coerced to numeric. instead of a proportional odds model each time? This is at the expense of the weights being less accurate. Default is
TRUE.missingness_methodHow to handle missing values in covariates.
design_formulaA formula object.
...Extra arguments passed to the
DesignSeqOneByOneKK21superclass.
Examples
seq_des = DesignSeqOneByOneKK21stepwise$new(n = 6, response_type = "continuous")Examples
seq_des = DesignSeqOneByOneKK21stepwise$new(n = 6, response_type = 'continuous')
seq_des$add_one_subject_to_experiment_and_assign(data.frame(x1 = rnorm(1)))
#> [1] 1
## ------------------------------------------------
## Method `DesignSeqOneByOneKK21stepwise$new()`
## ------------------------------------------------
if (FALSE) { # \dontrun{
seq_des = DesignSeqOneByOneKK21stepwise$new(n = 6, response_type = "continuous")
} # }