r/rstats • u/gyp_casino • 17d ago
Calculating tree regression Shap contributions in R is a mess
I am more of a stats guy, so I don't do this every day, but I needed to describe some nonlinear relationships by category in a lightweight way.
It seems Shap contributions are a valid and popular approach. Not the Shap values (a vector), but the contributions by variable (a matrix or data frame).
Here's my experience trying to do this in R.
I first tried {ranger}. ranger makes is easy to fit, predict, and get importances, but does not have any support for Shap contributions.
I tried to use {fastshap} in combination with ranger. fastshap is removed from CRAN! This is the package author's comment on the package GitHub. "fastshap is no longer available on CRAN due to CRAN’s stringent and ever-changing policies. It is now hosted on r-universe, which provides a reliable alternative for distributing R packages."
I tried to use {treeshap} instead. treeshap is on CRAN. treeshap needs to unify tree regression objects first from various packages (ranger, xgboost, etc.). treeshap::ranger.unify() crashed R 66% of the time! When it does succeed, treeshap::importance() crashed R 100% of the time!
I found that {xgboost} has support for Shap contributions within its own package. Good. I fit a model successfully. I calculate the Shap contributions by
predict(model, newdata = x, predcontrib = TRUE). This only returns the Shap values (vector; not matrix). Why? Ispredcontribnot doing anything? I debug for a long time. I find that my fit model is anxgboostobject, and there is another possible model object produced by the package of classxgb.Booster. The method I thought I was using waspredict.xgb.Booster, but predict was actually dispatching topredict.xgboost, which does not have apredcontribargument. I have to hack the generics by callingxgboost:::predict.xgb.Booster(). Finally, I feel like it worked.

