High-Performance Open-Source Archive
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).
Need mirroring services?
Contact our team at info@vpspulse.com.
Mirror powered by VPSpulse
Infrastructure sponsored by VPSPulse & Secure Payments by ArionPay.