Adaptive Alpha Adjustment Based on Power Decay
alpha_adaptive.RdFactory function that returns a closure for use with
find_blocks. The returned function adjusts significance
levels at each tree depth based on estimated power decay, using the
adaptive-alpha framework of Appendix B of the supplement.
Arguments
- k
Branching factor. Either a scalar (constant k at all levels) or an integer vector of length
max_depthwherek[ell]is the branching factor at levelell.- delta_hat
Estimated standardized effect size (e.g., Cohen's d). Conservative (larger) values produce more stringent adjustment, which preserves the FWER guarantee. Use an upper bound on the true effect size.
- N_total
Total sample size at the root level.
- max_depth
Maximum depth to compute (default 20).
- budget_weights
Controls how the error budget is allocated across depths. Same options as in
compute_adaptive_alphas_tree:NULL(default, telescoping),"equal","proportional", or a numeric vector of lengthmax_depth - 1that sums to at most 1.
Value
A function with signature
function(pval, batch, nodesize, thealpha, thew0, depth)
conforming to the alphafn interface used by
find_blocks.
Details
The returned function uses the depth parameter (passed by
find_blocks) to look up the pre-computed alpha for each
node's tree depth. The pval, batch, nodesize,
and thew0 parameters are accepted for interface compatibility
but are not used — unlike online FDR methods, the adaptive alpha
depends only on tree structure, not on observed p-values.
Results are cached internally: the vector of adjusted alphas is
computed once per unique value of thealpha and reused on
subsequent calls. When the error load is at most 1 (natural gating
suffices), nominal alpha is returned at every level.
Examples
# Create an adaptive alpha function for a 4-ary tree
my_alpha <- alpha_adaptive(k = 4, delta_hat = 0.5, N_total = 1000)
# Use with find_blocks
# find_blocks(idat, bdat, ..., alphafn = my_alpha)
# Inspect the alpha schedule it will use
compute_adaptive_alphas(k = 4, delta_hat = 0.5, N_total = 1000)
#> 1 2 3 4 5 6
#> 0.0500000000 0.0125000000 0.0031250000 0.0007997540 0.0003946616 0.0005901563
#> 7 8 9 10 11 12
#> 0.0018817331 0.0082501914 0.0398561834 0.0500000000 0.0500000000 0.0500000000
#> 13 14 15 16 17 18
#> 0.0500000000 0.0500000000 0.0500000000 0.0500000000 0.0500000000 0.0500000000
#> 19 20
#> 0.0500000000 0.0500000000
#> attr(,"error_load")
#> attr(,"error_load")$G
#> 1 2 3 4 5 6
#> 0.000000e+00 4.000000e+00 1.600000e+01 6.251922e+01 1.266908e+02 8.472332e+01
#> 7 8 9 10 11 12
#> 2.657125e+01 6.060465e+00 1.254510e+00 2.530954e-01 5.072969e-02 1.015148e-02
#> 13 14 15 16 17 18
#> 2.030573e-03 4.061285e-04 8.122640e-05 1.624531e-05 3.249065e-06 6.498130e-07
#> 19 20
#> 1.299626e-07 2.599252e-08
#>
#> attr(,"error_load")$sum_G
#> [1] 328.1361
#>
#> attr(,"error_load")$needs_adjustment
#> [1] TRUE
#>
#> attr(,"error_load")$thetas
#> 1 2 3 4 5 6 7
#> 1.00000000 1.00000000 0.97686288 0.50660747 0.16718519 0.07840595 0.05702089
#> 8 9 10 11 12 13 14
#> 0.05174976 0.05043709 0.05010925 0.05002731 0.05000683 0.05000171 0.05000043
#> 15 16 17 18 19 20
#> 0.05000011 0.05000003 0.05000001 0.05000000 0.05000000 0.05000000
#>
#> attr(,"error_load")$critical_level
#> [1] 5
#>
#> attr(,"error_load")$n_by_level
#> 1 2 3 4 5 6
#> 1.000000e+03 2.500000e+02 6.250000e+01 1.562500e+01 3.906250e+00 9.765625e-01
#> 7 8 9 10 11 12
#> 2.441406e-01 6.103516e-02 1.525879e-02 3.814697e-03 9.536743e-04 2.384186e-04
#> 13 14 15 16 17 18
#> 5.960464e-05 1.490116e-05 3.725290e-06 9.313226e-07 2.328306e-07 5.820766e-08
#> 19 20
#> 1.455192e-08 3.637979e-09
#>