
Risk Difference Inference for Incidence Responses
Source:R/inference_incidence_risk_diff.R
InferenceIncidRiskDiff.RdFits a linear probability model \(E[Y \mid w, x] = \beta_0 + \beta_T w +
\beta_X^\top x\) via ordinary least squares for binary (incidence) responses
\(Y \in \{0,1\}\), using the treatment indicator \(w\) and, optionally,
all recorded covariates \(x\) as predictors. \(\hat\beta_T\) is reported
directly as the risk-difference estimate: because \(Y\) is 0/1, the OLS fit
coincides with a saturated/linear model for the conditional risk
\(P(Y=1\mid w,x)\), so the coefficient on \(w\) is already on the
risk-difference (probability) scale with no back-transformation needed. This
is a misspecified working model for a binary response (heteroskedastic,
errors not Gaussian: \(\mathrm{Var}(Y \mid w,x) = P(w,x)(1-P(w,x))\) varies
by treatment arm and covariates, so a single pooled residual variance is
the wrong variance model), so likelihood_tier = "none": standard
errors and the Wald CI use the Huber-White (HC0) sandwich
variance of \(\hat\beta_T\) – \((X'X)^{-1} X'\,\mathrm{diag}(e_i^2)\,X\,
(X'X)^{-1}\), from the OLS residuals \(e_i\) – not the classical
homoskedastic OLS variance and not a binomial likelihood, and no
likelihood-ratio or parametric-bootstrap methods are exposed.
Super class
Inference -> InferenceIncidRiskDiff
Methods
+ inherited public methods from Inference
Inference$capabilities()Inference$compute_exact_confidence_interval()Inference$compute_exact_two_sided_pval_for_treatment_effect()Inference$duplicate()Inference$get_analysis_data()Inference$get_covariates()Inference$get_design_object()Inference$get_model_formula()Inference$get_nonestimable_reason()Inference$get_nonestimable_stage()Inference$get_optimization_alg()Inference$get_response()Inference$get_response_type()Inference$get_treatment()Inference$is_nonestimable()Inference$set_optimization_alg()Inference$set_seed()Inference$supports()
InferenceIncidRiskDiff$new()
Uses the randomization-CI layer's two-sided p-value contract
(InferenceRandCI's version, not
InferenceRand's): for incidence responses it dispatches to the
Zhang exact randomization test rather than refusing outright, matching
this class's pre-migration old-ladder behavior. This deliberately
differs from the InferenceAllSimpleAverageDiff-family precedent of
pinning InferenceRand's version, which would have regressed the
working Zhang dispatch this class had on the old ladder.
Initialize a risk-difference inference object.
Usage
InferenceIncidRiskDiff$new(
des_obj,
model_formula = NULL,
verbose = FALSE,
smart_cold_start_default = NULL
)Arguments
des_objA completed
Designobject with an incidence response.model_formulaOptional formula for covariate adjustment. If
NULL(default), the formula from the design object is used and its pre-computed design matrix is reused. If a formula is provided, a new design matrix is constructed from the design's imputed covariates.verboseWhether to print progress messages.
smart_cold_start_defaultWhether to use smart cold start values.
rNumber of randomization vectors. @param delta Null difference.
transform_responsesTransformation. @param na.rm Remove NAs.
show_progressShow progress. @param permutations Pre-computed permutations.
typeOptional exact-inference type for incidence dispatch.
args_for_typeOptional arguments for
type.zero_one_logit_clampClamp for exact 0/1 values when logging.
InferenceIncidRiskDiff$compute_estimate()
Fits the OLS linear-probability model and returns the
risk-difference point estimate \(\hat\beta_T\), the coefficient on
treatment. On a hardened design (private$harden), or when
estimate_only = FALSE, delegates to fast_ols_with_var_cpp()
via the shared model cache so the variance is available for later
confidence-interval/p-value calls without refitting.
InferenceIncidRiskDiff$compute_asymp_confidence_interval()
Wald confidence interval for the risk difference,
\(\hat\beta_T \pm z_{1-\alpha/2}\, \hat s(\hat\beta_T)\), using the
Huber-White (HC0) sandwich standard error from the cached
model fit (see the class-level documentation) and a normal-quantile
multiplier – fast_ols_with_var_cpp() doesn't report residual
degrees of freedom, so private$compute_z_or_t_ci_from_s_and_df()
always falls back to its \(z\) branch here, never a \(t\)
reference, regardless of \(n\). Interval bounds are not clamped to
\([-1, 1]\); a linear-probability model can produce out-of-range
endpoints near the boundary of the covariate space.
InferenceIncidRiskDiff$compute_asymp_two_sided_pval()
Two-sided Wald test of \(H_0: \beta_T = \delta\) vs.
\(H_1: \beta_T \neq \delta\), via the Wald statistic
\((\hat\beta_T - \delta) / \hat s(\hat\beta_T)\) (\(\hat s\) the
Huber-White sandwich SE) referred to a standard normal distribution
– same \(z\), not \(t\), reference as
$compute_asymp_confidence_interval(), for the same reason
(no residual degrees of freedom are ever cached for this class).
InferenceIncidRiskDiff$compute_estimate_with_bootstrap_weights()
Refits the linear-probability model by weighted least squares
(stats::lm.wfit()) under subject/block resampling weights
(nonparametric-bootstrap replicate weights or Bayesian-bootstrap Dirichlet
weights, both expanded to row weights via
expand_subject_or_block_weights_to_row_weights()) and returns the
re-estimated treatment coefficient. Rows with non-finite or non-positive
weight are excluded; if too few positive-weight rows remain to identify
the design, the replicate estimate is NA_real_.
Usage
InferenceIncidRiskDiff$compute_estimate_with_bootstrap_weights(
subject_or_block_weights,
estimate_only = FALSE
)Arguments
subject_or_block_weightsNumeric weights, one per subject or per resampling block (matched pair/cluster), as produced by the bootstrap or Bayesian-bootstrap resampling machinery.
estimate_onlyAccepted for interface compatibility; standard errors are never computed for a single bootstrap replicate regardless of this flag (only the point estimate is used to build the bootstrap distribution).
Examples
# \donttest{
seq_des = DesignSeqOneByOneBernoulli$new(n = 10, response_type = 'incidence')
for (i in 1:10) {
seq_des$add_one_subject_to_experiment_and_assign(data.frame(x1 = rnorm(1)))
}
seq_des$add_all_subject_responses(rbinom(10, 1, 0.5))
inf = InferenceIncidRiskDiff$new(seq_des)
inf$compute_estimate()
#> [1] -0.4046069
# }