0.3.0 introduced the right correction. This release makes it survive contact with real stacked data, and derives the degrees of freedom instead of relying on a p-value that has usually underflowed by the time it is needed. Results will differ from 0.3.0.
ctree_stacked() no longer aborts on large stacked datasetspartykit stores node-level p-values on the natural scale, and they underflow
to exactly 0 once the statistic passes roughly 1400 at df = 2. On stacked
data that is the normal case, not an edge case: 3,000 rows with M = 30 already
produces a root statistic above 5,000. 0.3.0 recovered the degrees of freedom
by inverting the stored p-value and, failing that, stopped with
could not recover degrees of freedom at node 1 (statistic = 5187.76,
p = 0). Refusing to prune on unverified statistics.
so the package could not fit the kind of dataset it was written for. 1.0.0
recovers df where the stored p-value is interior and falls back on the
structural rule (below) where it is not, and computes the corrected p-value as
-expm1(k * pchisq(stat, df, lower.tail = TRUE, log.p = TRUE)), which stays
accurate to about 1e-300 rather than collapsing to 0.
With teststat = "quadratic" the node-level statistic is chi-square with df
equal to the rank of the covariance matrix of the linear statistic:
df = the outcome dimension, so 1 for a
univariate outcome, 2 for a bivariate outcome, 3 for three outcomes;L levels present in that node: (L - 1) times
the outcome dimension, which changes from node to node as levels drop out of
a branch.ctree_stacked() and prune_stackM() recover an integer df for every
candidate variable at every node, by inverting the (statistic, p-value) pairs
partykit stored, and cross-check the result against the structural rule.
ctree splits a node when any candidate variable meets alpha, and that is
the rule the correction must reapply. Rescaling can reorder the candidates,
because they carry different degrees of freedom, so the variable with the
smallest p-value before the correction is not always the smallest after.
node_stats gains p_min and variable_min recording the decisive candidate,
and the full per-candidate table is attached as
attr(node_stats, "candidates").
An internal node is collapsed only once all of its own internal descendants have been collapsed, so a node whose descendant survives the correction keeps its split. This is the compression order described in the paper. Trees will therefore retain some splits that 0.3.0 removed.
prune_stackM() handles a default ctree() fitctree_stacked() grows with testtype = "Univariate" so that the stored
p-values are raw, but prune_stackM() is documented as accepting any tree
fitted on stacked data, and partykit's default is testtype = "Bonferroni",
where the stored p-values already carry the multiplicity adjustment. Inverting
those as if they were raw returned a plausible but wrong df (2.32 instead of
2; 12.05 instead of 8 in testing) and the internal verification could not
detect it, because it re-solved the same equation it had just inverted.
1.0.0 reads the multiplicity setting from the fitted control and inverts the
matching relationship, and check_stackM_extraction() now exercises both
settings and checks the recovered df against the structural rule rather than
against itself.
rescale_alpha() is removedIt implemented the alpha / M rule from 0.1.0-0.2.0, which is not the Stack/M
correction, and by 0.3.0 its entire help page was an explanation of why not to
use it. Deprecating it kept a function in the index whose only purpose was to
document a mistake. Code that still calls it will now fail with
could not find function "rescale_alpha"; the replacement is
[rescale_statistic()], or [ctree_stacked()], which applies the correct rule
automatically.
minsplit and minbucket are multiplied by M (scale_minsize = TRUE), so
they refer to original rather than stacked observations. The partykit
defaults previously allowed terminal nodes holding fewer than one original
observation.y ~ . formula can no longer split on imputation number. The
documented usage in 0.3.0 invited exactly that.NAMESPACE was out of date: prune_stackM(), rescale_statistic() and
check_stackM_extraction() had @export tags but were not exported, so
they were unreachable despite being advertised in DESCRIPTION.ctree_stacked() gains df and scale_minsize arguments. formula,
data, m, alpha and verbose are unchanged.teststat = "maximum", testtype = "MonteCarlo" or
splittest = TRUE are rejected with an explanatory error rather than
silently rescaled: those settings do not use a chi-square reference
distribution.summary.ctreeMI() by name; the method is
registered for S3 dispatch but not exported, so the call failed and
R CMD check did not pass on 0.3.0.README.md still described the alpha / M rule from 0.1.0-0.2.0 and
pointed at a repository URL that does not exist; both corrected.test-stackM-numerics.R; a
version number in a filename becomes archaeology at the next release.R/zzz.R. The .onLoad() / registerS3method() workaround is
unnecessary now that NAMESPACE carries the S3method() entries, and it
registered only two of the four methods.Versions 0.1.0 and 0.2.0 did not implement the Stack/M correction of
Sherlock et al. (2026). They divided the significance threshold by M and
passed alpha / M to ctree_control(). The published and validated method
divides the node-level chi-square statistic by M and recomputes the
p-value.
These are not equivalent. Writing q(p, df) for the chi-square quantile
function, the statistic rule rejects when X > M * q(1 - alpha, df) while
the threshold rule rejects when X > q(1 - alpha / M, df). They coincide
only at M = 1. At df = 1 and alpha = 0.05:
| M | statistic rule | threshold rule | |----|----------------|----------------| | 5 | X > 19.2 | X > 6.63 | | 10 | X > 38.4 | X > 7.88 | | 30 | X > 115.2 | X > 9.88 | | 50 | X > 192.1 | X > 10.83 |
Threshold rescaling therefore under-corrects severely, and trees fitted with 0.1.0-0.2.0 contain more splits than the published method supports. Refit any such tree with 0.3.0 and re-check any reported subgroups.
ctree_stacked() now grows the tree at the nominal alpha and then
applies the correction post hoc: node statistics are divided by M,
p-values recomputed, the multiplicity adjustment reapplied, and failing
nodes collapsed. Split selection in partykit does not depend on alpha,
and the correction is strictly stricter than the nominal threshold, so
this yields the same tree as growing under the corrected criterion.rescale_statistic(): divides a statistic by M and recomputes its
p-value.prune_stackM(): applies the correction to any party object
fitted on stacked data; returns the pruned tree and a per-node table of
raw and rescaled statistics.check_stackM_extraction(): diagnostic confirming node statistics
and degrees of freedom can be recovered from the installed partykit.rescale_alpha() is deprecated and now warns. It never implemented the
published correction.ctreeMI_info replaces alpha_nominal/alpha_applied with alpha,
correction, node_stats, n_splits_before and n_splits_after.report_ctreeMI() now describes the statistic-based correction and
reports how many candidate splits survived it.node_table(): returns a data frame of tree nodes with the split
path defining each node, its size in the stacked data, and its
effective sample size on the original scale (stacked size / M).report_ctreeMI(): generates a methods paragraph describing the
fitted model, populated with the actual M, sample sizes, significance
thresholds, and tree size.ctree_stacked(): fit a conditional inference tree on stacked multiply
imputed data with the Stack/M significance-threshold correction
(Sherlock et al., 2026).stack_imputations(): stack a list of imputed data frames vertically.rescale_alpha(): compute the Stack/M corrected significance threshold.print.ctreeMI() and summary.ctreeMI() S3 methods.mids objects from mice, lists of data frames, or plain data
frames (falls back to standard ctree with a warning).Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.