Documentation

API reference & usage guide.

Complete reference for all e2tree functions, S3 classes, and methods. Jump to any section via the sidebar.

Installation

Get e2tree on CRAN or GitHub.

# Stable release from CRAN install.packages("e2tree") # Stable version from GitHub install.packages("remotes") remotes::install_github("massimoaria/e2tree") # Development version from GitHub remotes::install_github("agostinognasso/e2tree")

Dependencies installed automatically: Rcpp, dplyr. Recommended: randomForest or ranger, rpart.plot, partykit.

No install? Try it in your browser.

e2tree ships as a WebAssembly build for webR — R running entirely in your browser, nothing to install. Open the REPL and paste:

Open webR REPL
webr::install(c("e2tree", "randomForest")) library(e2tree) library(randomForest) ensemble <- randomForest(Species ~ ., data = iris, proximity = TRUE) D <- createDisMatrix(ensemble, data = iris, label = "Species", parallel = list(active = FALSE)) tree <- e2tree(Species ~ ., iris, D, ensemble) print(tree)

Note: the webR build can lag behind the CRAN release by a version.

Quick start

Classification in 5 steps.

library(e2tree) library(randomForest) library(rsample) library(dplyr) # 1. Split data set.seed(42) iris_split <- iris %>% initial_split(prop = 0.75) training <- training(iris_split) validation <- testing(iris_split) # 2. Train a tree-based ensemble ensemble <- randomForest( Species ~ ., data = training, importance = TRUE, proximity = TRUE ) # 3. Compute the co-occurrence dissimilarity matrix D <- createDisMatrix( ensemble, data = training, label = "Species", parallel = list(active = FALSE) ) # 4. Fit the explainable tree setting <- list( impTotal = 0.1, maxDec = 0.01, n = 2, level = 5 ) tree <- e2tree(Species ~ ., training, D, ensemble, setting) # 5. Predict, measure fidelity, explain pred <- predict(tree, newdata = validation) val <- eValidation(training, tree, D, n_perm = 999) vi <- vimp(tree, data = training) plot(tree, ensemble = ensemble) # How faithfully does the tree reconstruct the ensemble? prox <- proximity(val) summary(loi(prox$ensemble, prox$e2tree)) # Explain a single case, in the ensemble's own terms explain(tree, ensemble, newdata = validation[1, ])
createDisMatrix()

Derives the co-occurrence dissimilarity matrix from any supported tree ensemble. Performance-critical computation runs in C++ via Rcpp with OpenMP; supports parallel execution and chunked computation for large samples.

createDisMatrix( ensemble, data, label, parallel = list(active = FALSE, no_cores = 1), verbose = FALSE, chunk_size = NULL, memory_limit = NULL, use_disk = FALSE )
ArgumentTypeDescription
ensembleensembleA fitted tree ensemble: randomForest, ranger, xgb.Booster, lgb.Booster, gbm, or catboost.Model.
datadata.frameThe training dataset used to fit the ensemble.
labelcharacterName of the response variable column.
parallellistactive: logical; enable parallel computation. no_cores: number of cores.
chunk_sizeintegerWhen smaller than the sample size, computes D in chunks to bound memory. use_disk = TRUE persists the result.

Returns: A symmetric numeric matrix of dimensions n × n with values in [0, 1] and zero diagonal, carrying an ensemble_backend attribute. Reusing a stale D with a different model raises a warning rather than producing a silent bug.

Interpretation note (bagging vs boosting). The dissimilarity scale differs systematically between backend families. Compare fidelity values within a backend, not across them.

e2tree()

Grows a single decision tree guided by the ensemble's dissimilarity structure. Returns an object of class e2tree.

e2tree( formula, data, D, ensemble, setting = list(impTotal = 0.1, maxDec = 0.01, n = 2, level = 5) )
ArgumentTypeDescription
formulaformulaStandard R formula specifying the response and predictors, e.g. Species ~ .
datadata.frameTraining dataset. Must match the data used to compute D.
DmatrixDissimilarity matrix produced by createDisMatrix().
ensemblerf / rangerThe original ensemble model. Used to extract terminal node assignments.
settinglistStopping rules: impTotal (min impurity), maxDec (min decrease), n (min observations), level (max depth).
predict.e2tree()

Predicts responses for new observations by routing them through the e2tree's split rules.

## S3 method for class 'e2tree' predict(object, newdata, ...)
ArgumentTypeDescription
objecte2treeA fitted e2tree model.
newdatadata.frameNew data to predict. Must contain the same predictor columns.

Also available: fitted(object) returns training predictions, residuals(object) returns training residuals.

eValidation()

Assesses reconstruction quality by comparing the ensemble proximity matrix with the one induced by the e2tree, using the nLoI plus four complementary divergence and similarity measures, each with a permutation test.

eValidation( data, fit, D, test = c("both", "mantel", "measures"), graph = TRUE, n_perm = 999, conf.level = 0.95, seed = NULL )
ArgumentTypeDescription
datadata.frameThe data frame containing the variables in the model.
fite2treeA fitted e2tree object.
DmatrixDissimilarity matrix from createDisMatrix().
testcharacter"measures" runs the divergence measures with permutation tests (agreement); "mantel" runs the Mantel test only (association); "both" is the default.
n_permintegerPermutations for the measure tests. 0 skips permutation testing.

Returns: An eValidation object holding both proximity matrices, the loi object with its decomposition, and a data frame of all measures (nLoI, Hellinger, wRMSE, RV, SSIM). Use measures(), proximity(), and plot().

vimp()

Computes global variable importance from the e2tree's split structure, weighted by the impurity decrease at each split. Classification or regression is auto-detected from the fitted object.

vimp(fit, data, type = NULL)

Returns: A list with the importance table (Variable, MeanImpurityDecrease) and $g_imp, a ggplot2 importance plot.

loi()

Loss of Interpretability. A scale-sensitive divergence measuring how faithfully the e2tree reconstructs the ensemble's co-occurrence structure — agreement, not association. Normalized by the pair count it yields the nLoI, bounded in [0, 1], zero if and only if the reconstruction is exact.

loi(O, O_hat, normalize = TRUE) ## Permutation test under simultaneous row/column permutation loi_perm(O, O_hat, n_perm = 999, conf.level = 0.95, seed = NULL)
ArgumentTypeDescription
OmatrixEnsemble proximity matrix (n × n), values in [0, 1]. Typically proximity(eValidation(...))$ensemble.
O_hatmatrixe2tree-induced proximity matrix (n × n). Crisp and block-diagonal: zero for every separated pair.
normalizelogicalTRUE (default) returns the nLoI, divided by M = n(n−1)/2; FALSE returns the raw LoI.

Returns: An object of class loi carrying the exact decomposition — loi_in / loi_out and their per-pair averages mean_in / mean_out, which are directly comparable. A high mean_out (> 0.3) means the partition is too coarse; a high mean_in (> 0.1) means poor within-node calibration.

localLoI()

Disaggregates the global nLoI into a per-node and per-observation component, so you can see where the reconstruction is reliable. A high per-observation value flags a case whose local explanation is less trustworthy.

localLoI(O, O_hat, fit = NULL)

Returns: An object of class localLoI with an obs and a node data frame. The per-observation values average back exactly to the global statistic: mean(obs$loi) == nLoI. Passing fit only relabels the detected blocks with the real terminal-node ids.

Local explainability

Per-instance explanations, verified against the ensemble.

e2tree is interpretive, not predictive: it reconstructs the grouping geometry a trained ensemble induces, and its quality is fidelity to that ensemble. This layer brings the same lens down to the individual observation. All functions are backend-agnostic.

explain()

A single per-instance entry point composing the whole local layer — routing, additive attribution, ensemble neighbours, region fidelity, outcome dispersion, and on request the counterfactual and stability — into one narrative object with print() and plot() methods.

explain( fit, ensemble, newdata, reliability = NULL, k = 5, alpha = 0.1, counterfactual = FALSE, stability = FALSE, B = 100, ... )
The components
FunctionWhat it answers
eContribution()Per-instance Saabas-style attribution of the reconstructed value. Exactly additive, per class for classification. A decomposition of the reconstruction, not of a prediction.
eNeighbors()Case-based explanation: the nearest training cases by the ensemble's own leaf co-occurrence proximity, plus leaf prototypes. Not a generic feature-space distance.
eCounterfactual()The smallest feature change moving an instance into a different region — validated against the ensemble's grouping geometry. validated is TRUE only when the forest actually regroups the counterfactual, unlike surrogate-only methods that merely flip the approximating tree.
eStability()Confidence and stability of a local explanation via bootstrap over the ensemble's trees. Yields a per-instance confidence, a neighbour-stability score, and an interval on the reconstructed outcome.
eHeterogeneity()Descriptive per-region outcome dispersion: entropy and prediction set for classification, central band and sd for regression.
nodeStats()Full profile of any node: metadata, decision rule, per-predictor node-vs-rest statistics (Cohen's d, Cramér's V) and the response distribution.
plotNodeComparison()Side-by-side comparison of two nodes on the predictors that separate them most.
Panel data

Longitudinal explanations, decomposed.

panel_e2tree()

On panel (unit × time) data with high intraclass correlation, a single pooled e2tree conflates two sources of variation and the within-unit signal is crowded out. panel_e2tree() decomposes the feature representation à la Mundlak (1978) into a between component (unit means, one row per unit) and a within component (unit-demeaned deviations), then grows a separate e2tree surrogate for each. The reconstruction is additive.

panel_e2tree( formula, data, unit, time = NULL, engine = c("ranger", "randomForest"), ntree = 500, target = c("outcome", "pooled"), within = c("unit", "twoway"), na.action = c("listwise", "unit.available"), min_periods = 1L, pooled_ensemble = NULL, dis_args = list(), ... )

Returns: An e2panel object with print(), summary() (fidelity plus decomposed between/within importance), plot() and predict(). Ships with the panel_health dataset — a simulated country × year panel with known between and within drivers. Regression outcomes with numeric predictors.

S3 methods

Standard interface for e2tree objects.

ClassMethods
e2treeprint, summary, plot, predict, fitted, residuals, as.rpart, as.party, nodes, e2splits
eValidationprint, summary, plot, measures, proximity
loiprint, summary, plot
loi_permprint, summary, plot
localLoIprint, summary, plot
e2explanationprint, plot
e2contributionprint, plot
e2neighborsprint, plot
e2counterfactualprint, plot
e2stabilityprint, plot
e2heterogeneityprint, plot
e2nodeStatsprint, plot
e2panelprint, summary, plot, predict
Interoperability

Convert to rpart and partykit.

e2tree objects can be converted to two widely-used R tree formats, unlocking the full ecosystem of tree visualization and inspection tools.

# Convert to rpart for rpart.plot rpart_obj <- as.rpart(tree, ensemble) rpart.plot::rpart.plot(rpart_obj) # Convert to partykit constparty if (requireNamespace("partykit", quietly = TRUE)) { party_obj <- partykit::as.party(tree) plot(party_obj) }
Accessors

Inspect the tree structure.

# All nodes as a data frame nodes(tree) # Terminal nodes only nodes(tree, terminal = TRUE) # Split information at each internal node e2splits(tree)