Repository navigation
Add Kenward-Roger's tests and F-tests to mixed models and dream - #53
Merged
Merged
Conversation
parashardhapola
force-pushed
the
44-gene-set-files
branch
from
October 26, 2026 15:46
f0c63a8 to
b76dfbb
Compare
Mixed models gain Kenward and Roger's method for tests of the fixed effects (adjusted covariance and degrees of freedom, as pbkrtest and lmerTest compute them) and F-tests of several contrasts by Satterthwaite's or Kenward and Roger's method. dream's moderated tests use either, with dream's moderated F-test, and dream_voom now chooses the degrees of freedom as dream does by default: Kenward and Roger's for groups of fewer than 20 samples, with dream's fallback to Satterthwaite's for ill-conditioned genes. dream_voom gains F-test tables, and its provenance records the random effects' variables. Checked against pbkrtest 0.5.3, lmerTest 3.1-3 and variancePartition 1.36.2 on lme4 1.1-38 (validation/kenward_roger_and_f_tests.py: 143 checks, none failed).
parashardhapola
marked this pull request as ready for review
October 26, 2026 15:49
parashardhapola
force-pushed
the
47-dream-kenward-roger-and-f-tests
branch
from
October 26, 2026 15:49
30e2463 to
b58125a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Most single-cell studies are small, and variancePartition's
dreamtests them withKenward and Roger's degrees of freedom by default (
ddf = "adaptive"), wheredream_voomused Satterthwaite's for every study. This adds Kenward and Roger's method(the adjusted covariance of the fixed effects and its degrees of freedom, for one
contrast and for several) and F-tests of several contrasts at once, as pbkrtest and
lmerTest compute them; dream's choice of degrees of freedom, now
dream_voom'sdefault, with dream's moderated F-tests; and the random effects' variables in
dream_voom's provenance. Everything is checked against pbkrtest 0.5.3, lmerTest 3.1-3and variancePartition 1.36.2 on lme4 1.1-38.
Changes
fixed_effect_tests(..., df_method="kenward_roger", kenward_roger_weights=...):t-tests with Kenward and Roger's adjusted standard errors and degrees of freedom
(lmerTest's
contest1D(ddf = "Kenward-Roger"), pbkrtest'svcovAdjandget_Lb_ddf).kenward_roger_weightssays how the adjustment takes precisionweights:
"average"(default), every observation at its feature's average weight,as dream computes it with pbkrtest;
"precision", each observation's own weight, themethod for the weighted model. Maximum likelihood fits are refused for Kenward and
Roger's method, as lmerTest refuses them.
fixed_effect_f_testand its resultFixedEffectFTest(new): the F-test thatseveral contrasts are all zero, by Satterthwaite's method as lmerTest's
contestMDor by Kenward and Roger's as pbkrtest's
KRmodcomp. Dependent contrasts test thespace they span; one contrast gives its t-test.
FixedEffectTestsgainskenward_roger_weightsandcovariance;MixedModelFitkeeps its
weightsandcomponent_levels, which Kenward and Roger's method needs.moderated_fixed_effect_testsmoderates Kenward-Roger tests too, andModeratedFixedEffectTestsgains dream's moderated F-test:f_statistic,f_df1,f_df2,f_p_valueandstandardized_f_statistic(topTable'sF.std).dream_voom(..., f_tests=None, df_method="adaptive", kenward_roger_weights="average").The default changes from Satterthwaite's degrees of freedom in every group to
dream's choice in each group: Kenward and Roger's for fewer than 20 samples,
Satterthwaite's otherwise, with dream's fallback (below).
df_method="satterthwaite"gives the old results.
f_tests={"time": ["t1_vs_t0", "t2_vs_t0"]}adds a table perF-test and group; a group that cannot estimate one of its contrasts lists the F-test
as not estimable. The summary gains
df_method; each group's recorddf_method,features_satterthwaite_fallbackandf_test_df1; the design's record the randomeffects and the values of the variables they group by, as
variance_partitioning'sdoes (the helper moved to
cytepool/_analysis_records.py).DifferentialExpressionResult.f_tests, andtable(group, name)finds F-tests.cytepool/stats/_fixed_effect_inference.py(private): the compiled Kenward-Rogercomputation, the degrees of freedom of contrasts, the F-tests and lmerTest's rule for
combining degrees of freedom, shared by the three modules.
models, REML and dream", the API pages, a capability matrix row, a Validation section
and summary row (31 scripts, 2,150 checks), the README, the Overview, a glossary
entry, and three references with DOIs checked against Crossref (Kenward and Roger
1997; Halekoh and Hojsgaard 2014; Fai and Cornelius 1996).
How dream behaves (found by running variancePartition 1.36.2)
ddf = "adaptive"used Kenward and Roger's method for 19 samples and Satterthwaite'sfor 20, on designs where the two differ, although its help page says "<= 20". So the
threshold is fewer than 20 samples, counted after a group's samples are filtered.
dreamreturns lmerTest'scontest1D(ddf = "Kenward-Roger")on lme4 fits whose weights are divided by their mean. Its standard errors are
pbkrtest's adjusted ones, and
eBayesadds the prior df to Kenward and Roger's.conditioned falls back to Satterthwaite's tests (variancePartition's NEWS for
1.31.16). On 450 genes built to straddle it, the bound is R's
kappa(vcovAdj)estimate above 1e6.
dream_voomuses the exact condition number, which decided all24 fallbacks of the validation's ill-conditioned cell type as dream did; the two can
differ within about 2% of the bound. The rule depends on the units of continuous
covariates, which the documentation says, with the remedy (centre and scale them).
topTable's F with several coefficients is limma's t' R^-1 t / r from the moderatedt-statistics and each gene's covariance (the adjusted one under Kenward and Roger),
reproduced to 4e-8.
Kenward and Roger's method with weights
pbkrtest builds the covariance of the observations without lme4's prior weights, while
it starts from the weighted fit's covariance of the coefficients (found by running
pbkrtest 0.5.3). With dream's weights divided by their mean, this treats every
observation as having its gene's average weight.
kenward_roger_weights="average"(thedefault) reproduces it, so that
dream_voommatches dream.It is not Kenward and Roger's method for the weighted model. That method is
"precision", checked against pbkrtest on the equivalent unweighted model: thevalues, fixed effects and random effects multiplied by the square roots of the weights.
With voom's weights the difference is not small. In the validation's weighted cases,
the average treatment gave standard errors 0.976 times the precision treatment's at the
median (0.51 to 1.05) and df 0.91 times (0.26 to 3.7). It also gave standard errors
below the unadjusted ones for 61% and 33% of the genes, which the precision treatment
never does. On the cube of
validation/dream.py(cell types of 16 and 13 samples),dream's treatment gave standard errors smaller than Satterthwaite's for 100% and 89% of
the genes, and the precision treatment larger ones for every gene.
How results change for small studies
Groups of fewer than 20 samples now get Kenward and Roger's tests. Compared with
Satterthwaite's tests, which
dream_voomused before:validation/dream.pycube, Bvalidation/dream.pycube, NKGroups of 20 samples or more are unchanged. No documentation notebook calls
dream_voom, and the outputs of all four checked notebooks are current.Deliberate differences from dream
topTablecomputes every gene's F-test p-value on the total df of the first gene forthe first coefficient listed (reproduced to 3e-14), so p-values change with the order
of genes and coefficients. CytePool gives each gene its own: F is the mean of r
squared uncorrelated moderated t-statistics, each with its contrast's df plus the
prior df, combined by lmerTest's rule. An F-test of one contrast is then the moderated
t-test. CytePool's p-values were 0.14 to 11.5 times dream's in the validation.
F.stduses the number of coefficients where they are dependent; CytePool their rank.Validation
validation/kenward_roger_and_f_tests.py(new): 143 checks, 115 pass, 16 information,12 deliberate differences, none failed.
validation/dream.pyprints the same 63 checksas before, now asking
dream_voomfordf_method="satterthwaite", which its R sideruns.
vcovAdj, lmerTestsummaryandcontest1DKRmodcomp, lmerTestcontestMDcontestMDcontestMDsummaryddfon studies of 12, 18, 19, 20 and 24 samples: weights, standard errors, df, moderated t, B, z, p-values and FvoomWithDreamWeights,dream,eBayes,topTabledream_voomwith its default on cubes of 12, 15 (ill conditioned) and 24 samplestopTablekappaReference: R 4.4.3, variancePartition 1.36.2, limma 3.62.1, lme4 1.1-38, lmerTest
3.1-3, pbkrtest 0.5.3, minqa 1.2.8.
Tests
tests/test_kenward_roger_and_f_tests.py(new, 42 tests, 2 s with compiled codecached):
for dream's moderated tests and
dream_voom's default;adjustment vanishes; in a randomised block design the df are the classical ones and
the F-test of the treatments is the analysis of variance's, by both methods;
lmerTest's rule for combining df on values derived by hand;
equal to its t-test (also below 2 df, as
contestMDgives it, and for dream'smoderated F), relabelled donors and reordered samples, the scale of the weights,
equal weights against none, and the number of threads;
dream_voom: its choice per group, the F tables and records, the fallback, an F-testa group cannot estimate, and the error messages.
Updated:
test_mixed_models.py,test_dream.py(its dream fixture isddf = "Satterthwaite", so it asks for that),test_masked_inputs.pyandtest_private_names.py. Fixtures:tests/data/kenward_roger_and_f_tests/, 24 files,each under 40 KB. The full suite: 4,141 passed, 18 skipped, also with bounds checks and
with the rounding changed.
Costs on one thread for 20,000 genes: Kenward and Roger's tests take 0.65 s at 20
samples and 13.5 s at 120 (Satterthwaite's 0.1 s).
For later
Random slopes (planned for 0.2); F-tests in
limma_voomandlimma_trend; Kenward andRoger's method for maximum likelihood fits (refused, as lmerTest does); a faster
adjustment for large studies; sample quality weights for dream.