Explainable Ensemble Trees
Overview
The Explainable Ensemble Trees 'e2tree' approach has been proposed by Aria et al. (2024) doi:10.1007/s00180-022-01312-6. It aims to explain and interpret decision tree ensemble models using a single tree-like structure. 'e2tree' is a new way of explaining an ensemble tree trained through 'randomForest' or 'xgboost' packages.
Robustness fixes (2026-05)
- **CatBoost multi-class leaf extraction**: for multi-class objectives (
MultiClass,MultiClassOneVsAll)catboost.predict(..., prediction_type = "RawFormulaVal", ntree_start, ntree_end)returns ann_obs x n_classesmatrix rather than a scalar vector, which broke the leaf-proxy assignment withError in leaf_mat[, t] <- as.integer(factor(round(raw, digits = 10L))) : number of items to replace is not a multiple of replacement length. The CatBoost adapter now collapses the per-tree raw-score matrix into a single key per observation (concatenation of the rounded class scores) before discretising into a leaf proxy. The single-output regression case is unchanged.
Show all changes in 1.2.0Hide the rest of the changes in 1.2.0
- **CatBoost loss-function parsing**: in some catboost releases the
loss_functionreturned bycatboost.get_model_params()is a list (e.g.list(type = "MultiClass", border = 0.5)) instead of a bare character scalar. The previous detection code piped this list directly intostartsWith()and failed withError: non-character object(s). The new.catboost_extract_loss()canonicalises any of the documented shapes (plain character, list-with-type, list-with-name, list whose first element holds the name) to a length-one character string before classification/regression dispatch and falls back toattr(ensemble, "params")whencatboost.get_model_params()does not expose the loss. - **CatBoost 1.2.x compatibility**: starting from
catboost1.2 the R objects returned bycatboost.train()carry the classcatboost.Modelinstead of the previouscatboost.CatBoost. All three S3 generics in the adapter layer (get_ensemble_type,extract_terminal_nodes,get_ensemble_predictions) now register methods for both class names, sharing a single internal worker, so models trained with either version are accepted out of the box.ensemble_backend()and.SUPPORTED_BACKENDSrecognise both class names.createDisMatrix()now sets thee2tree_labelattribute on CatBoost ensembles automatically when the user passeslabel, eliminating the previously required manualattr(ensemble, "e2tree_label") <- ...step. - **
moda()accepts non-factor responses**: classification ensembles trained on integer 0/1 responses (typical ofgbmwith thebernoullidistribution) no longer triggerError in res[1] <- as.character(levels(x)[res[1]]) : replacement has length zero. The internalmoda()helper now coerces the modal value to character independently of whether the response is a factor, an integer, a character or a numeric vector. Affected call sites:eStoppingRules(),e2tree(),vimp(). - **Vignette
models.Rmdcorrected**: the regression examples now pass the response column throughdatatogether withlabel = "<response_name>", as required bycreateDisMatrix()for regression backends; thegbmregression example setsn.minobsinnode = 2andbag.fraction = 0.8so it does not fail thegbminternal sample-size check on the smallmtcarstraining set; thelightgbmregression example usesnum_leaves = 8andmin_data_in_leaf = 2, which prevents the small-sample degenerate case caught byvalidate_terminal_nodes(). The classification example based on the binaryis_setosaindicator now passes a factor copy of the response toe2tree()while leaving the numeric copy togbm.
Multi-backend hardening (2026-04)
- **Adapter contract validation**:
createDisMatrix()now callsvalidate_terminal_nodes()immediately afterextract_terminal_nodes(). Malformed adapter output (wrong row count, non-numeric leaf columns, or the all-same-leaf degenerate case that previously made GBM silently produce an all-zeroD) is now rejected with an informative error. - **Backend tagging**: dissimilarity matrices returned by
createDisMatrix()carry a newensemble_backendattribute identifying the backend used.e2tree()andas.rpart()warn when the supplied ensemble does not match this tag, catching the common "staleDreused with a different model" mistake. - **xgboost 3.x compatibility**: models built via the high-level
xgboost::xgboost()wrapper (which adds anxgboostclass on top ofxgb.Booster) are now handled correctly; previously the wrapper'spredict.xgboostmethod rejectedxgb.DMatrixinput and broke leaf extraction. - **Chunked dissimilarity path wired in**: when
chunk_size < n_obsthe function now actually usescompute_dissimilarity_chunked()(previously the parameter was accepted but ignored). Optionaluse_disk = TRUEpersists the result viasaveRDS(). - **C++ type checks**:
compute_cooccurrences_cpp(),compute_cooccurrences_sparse_cpp()andcompute_all_cooccurrences_cpp()now validate thatTree*andrespcolumns are integer/double, raising a clear error rather than silently coercing factors/characters to zeros. - **Adapter de-duplication**: the three S3 generics share a single
.unsupported_backend()helper and a single supported-classes list; the xgboost adapters share a.xgb_dmatrix()builder. - **Documentation**:
?createDisMatrixnow contains an "Interpretation note (RF vs boosting)" section explaining why the dissimilarity scale differs systematically between bagging and boosting backends. - **Tests**: new
tests/testthat/test-multi-backend.Rexercises the D invariants (square, zero diagonal, symmetric, non-degenerate, correctly tagged) for each available backend, and covers the validator and the default-method failure paths.
S3 class system overhaul
e2treeclass now properly listed as first in the class vector (c("e2tree", "list")).- New S3 methods for
e2tree:predict(),fitted(),residuals(). predict.e2tree()replacesePredTree()as the standard prediction interface. For regression, returns a data frame withfitandsd(node-level standard deviation). For classification, returns a data frame withfit,accuracy, andscore.fitted.e2tree()returns fitted values for training data.residuals.e2tree()returns residuals for regression E2Trees.methods(class = "e2tree")now shows:as.rpart,e2splits,fitted,nodes,plot,predict,print,residuals,summary.methods(class = "eValidation")now shows:measures,plot,print,proximity,summary.
Accessor functions (new)
nodes(): Extract tree node data frame from ane2treeobject, with optionalterminalfilter.e2splits(): Extract split and categorical split information.measures(): Extract validation measures from aneValidationobject.proximity(): Extract proximity matrices (ensemble, e2tree, or both) from aneValidationobject.
Coercion methods (new)
as.rpart(): Generic and method for convertinge2treetorpartformat.as.party(): Method for convertinge2treetopartykit'sconstpartyformat (registered conditionally when partykit is installed). Produces proper bar plots in terminal nodes for classification trees.rpart2Tree()retained for backward compatibility with a deprecation note.
Validation framework improvements
eValidation()gains atestargument:"mantel"(Mantel test only),"measures"(divergence/similarity measures only), or"both"(default). This allows choosing between association testing and agreement testing.print.eValidation(),summary.eValidation(), andplot.eValidation()updated to handle all three test modes gracefully.
Variable importance improvements
vimp(): Auto-detects classification/regression from thee2treeobject;typeargument now optional.- Fixed incorrect y-axis label ("Variance" instead of "Variable") in variable importance plots.
- Regression variable importance bars now sorted by importance (previously unsorted).
- Consistent column naming (
Variable,MeanImpurityDecrease) across classification and regression. - Internal logic refactored into
.vimp_classification()and.vimp_regression().
Documentation
- All man page titles standardized to Title Case.
\dontrun{}replaced with\donttest{}in all examples; interactive-only examples wrapped inif (interactive()).- Examples updated to use accessor functions and
predict()instead of direct$access. - New vignette
e2tree-introductioncovering classification, regression, validation (Mantel test, divergence measures, LoI decomposition), and comparison with partykit/stablelearner. ePredTree()documentation updated with deprecation note pointing topredict.e2tree().
Package infrastructure
- Added
partykit,knitr,rmarkdownto Suggests. - Added
VignetteBuilder: knitrto DESCRIPTION. e2treeobject now storesfitted.values,y, anddatafor S3 method support.- Conditional
.onLoadhook for registeringas.party.e2treewhen partykit is loaded.
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-05
- NOTE12 OK, 1 NOTE2026-08-01
- OK14 OK2026-04-22
- ERROR13 OK, 1 ERROR2026-04-18
- OK14 OK2026-03-10
Documentation
- Help pages
- 34 (5 internal)
- Examples that run
- 0%17 only when donttest examples are enabled (R CMD check --as-cran)
- Exported functions with examples
- 59%
- Documented parameters
- 96%
- Return-value docs
- 91%
- Help pages citing references
- 0%
Downloads
Repository
- PRs merged (all time)
- 91%
- Median days to close, 50 most recently updated closed issues
- 21
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Forks over time
Releases over time
Issues over time
PRs over time
4 development-tooling and community-health practices detected across 2 families in the upstream repository
Checks run against github.com/massimoaria/e2tree on 2026-10-18.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2023-05-29
Dependencies
Installing e2tree adds 44 packages (23 with compiled code, 36 MB of source tarballs). Heaviest: stringi 11 MB, ggplot2 6.0 MB, Rcpp 1.8 MB.
Code & Tests
Datasets
People & History
Pick two releases to compare their code metrics.
- 1.2.0Latest2026-05-15 · current release · diff ↗ ·
removed 3 exports
goi, goi_analysis, goi_permadded 10 exports
as.rpart, e2splits, extract_terminal_nodes, get_ensemble_predictions, get_ensemble_type, loi, loi_perm, measures, nodes, proximity - RR 4.6.0 released · 2026-04-24
- 1.0.02025-07-16 · diff ↗ ·
removed 1 export
eComparisonadded 9 exports
eValidation, goi, goi_analysis, goi_perm, plot_e2tree, plot_e2tree_click, plot_e2tree_vis, print_e2tree_summary, save_e2tree_html - 0.2.02025-07-16 · diff ↗
- 0.1.22025-04-12
- RR 4.5.0 released · 2025-04-11
Package metadata
- First published
- 2025-04-12
- Total releases
- 4 / 1 yrs
- License
- MIT + file LICENSE OSI
- Minimum R
- ≥ 3.5
- Bundled data
- 2.1 KB / 1 file
- Download size
- 3.4 MB
Cite
Cite this package
Run in R for the authors' entry:
citation("e2tree")The package provides a citation file, so citation() returns the authors' own entry.
It points to 10.1007/s00180-022-01312-6, 10.1002/asmb.70064.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-21, which the citation names so these numbers can be found later. More on citing and the projects behind them.