0Pricing
R Academy · Lesson

Feature Importance and Model Interpretation

Extract and visualize variable importance and SHAP values from ensemble models.

Feature Importance and Model Interpretation is a free R Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Model Interpretation Matters

Accurate models that nobody trusts are useless in practice. Model interpretation answers two questions: Which features matter most globally? (global importance) and Why did the model make this specific prediction? (local explanation). Both XGBoost and ranger provide built-in tools for global importance, while SHAP values enable local explanations.

# The interpretation toolkit we will use:
# - xgb.importance()      XGBoost global importance
# - xgb.plot.importance() Visualise XGBoost importance
# - ranger importance     Random forest importance
# - shapviz package       SHAP value computation + plots

cat('Packages needed: xgboost, ranger, shapviz')

xgb.importance() — Three Metrics

xgb.importance(model) returns a data frame with three importance metrics for each feature:

  • Gain: average improvement in loss from splits on this feature (most informative).
  • Cover: average number of observations affected by splits on this feature.
  • Frequency: proportion of splits that used this feature.
library(xgboost)
library(MASS)

X <- as.matrix(Boston[, -14])
y <- Boston[, 14]
dtrain <- xgb.DMatrix(data = X, label = y)

params <- list(objective = 'reg:squarederror', eta = 0.1,
               max_depth = 5, subsample = 0.8)
model  <- xgboost(data = dtrain, params = params,
                  nrounds = 100, verbose = 0)

imp <- xgb.importance(model = model, feature_names = colnames(X))
print(head(imp))

xgb.plot.importance()

xgb.plot.importance(importance_matrix) creates a horizontal bar chart of feature importances. By default it uses the Gain metric. The top_n argument limits output to the most important features for clarity.

imp <- xgb.importance(model = model, feature_names = colnames(X))

# Plot top 10 features by Gain
xgb.plot.importance(
  importance_matrix = imp,
  top_n  = 10,
  measure = 'Gain',
  main   = 'XGBoost Feature Importance (Gain)'
)

ranger Variable Importance

ranger supports two importance measures: 'impurity' (fast, computed during training) and 'permutation' (slower, but measures the actual impact of each feature on predictions). Permutation importance is generally preferred for reliable rankings.

library(ranger)

# Impurity importance (fast)
rf_imp <- ranger(
  medv ~ ., data = MASS::Boston,
  num.trees  = 500,
  importance = 'impurity'
)
imp_impurity <- rf_imp$variable.importance

# Permutation importance (more reliable, slower)
rf_perm <- ranger(
  medv ~ ., data = MASS::Boston,
  num.trees  = 500,
  importance = 'permutation'
)
imp_permutation <- rf_perm$variable.importance

cbind(impurity = sort(imp_impurity, dec=TRUE),
      permutation = sort(imp_permutation, dec=TRUE))

Comparing ranger and XGBoost Importance

Different models assign different importance scores because they measure different things. Impurity-based importance (ranger default) can be biased towards high-cardinality features. Permutation importance is more robust. XGBoost's Gain is usually the most informative of its three metrics.

# Align rankings for comparison
xgb_rank <- imp$Feature
rf_rank  <- names(sort(rf_perm$variable.importance, dec=TRUE))

# Spearman rank correlation between the two rankings
shared <- intersect(xgb_rank, rf_rank)
xgb_pos <- match(shared, xgb_rank)
rf_pos  <- match(shared, rf_rank)

cor(xgb_pos, rf_pos, method = 'spearman')

What Are SHAP Values?

SHAP (SHapley Additive exPlanations) values decompose each prediction into contributions from each feature, grounded in game theory. For a prediction on one observation, SHAP values sum to the difference between the model output and the baseline (average prediction). This enables both global and local explanations.

XGBoost supports tree SHAP natively via predict(model, data, predcontrib = TRUE).

# Compute SHAP values natively from XGBoost
shap_matrix <- predict(
  model,
  newdata     = dtrain,
  predcontrib = TRUE  # returns SHAP contributions
)

# Result: matrix with one column per feature + BIAS column
dim(shap_matrix)  # rows x (features + 1)
colnames(shap_matrix)

shapviz Package Basics

The shapviz package provides a rich visualisation layer on top of SHAP values. Pass the raw SHAP matrix and the feature matrix to shapviz(), then use plotting functions like sv_importance(), sv_waterfall(), and sv_beeswarm().

library(shapviz)

# Build shapviz object from XGBoost model
shp <- shapviz(model, X_pred = X)

# Global importance: mean |SHAP| per feature
sv_importance(shp, kind = 'bar')

# Beeswarm plot (SHAP summary plot)
sv_importance(shp, kind = 'beeswarm')

Waterfall Plot — Local Explanation

A waterfall plot explains a single prediction: it shows how each feature pushed the prediction above or below the baseline. Positive SHAP values (red bars) increase the prediction; negative values (blue bars) decrease it. The baseline is the average model output.

library(shapviz)

shp <- shapviz(model, X_pred = X)

# Explain the prediction for observation 1
sv_waterfall(shp, row_id = 1) +
  ggplot2::labs(
    title = 'SHAP Waterfall — Observation 1',
    subtitle = 'How each feature contributed to this prediction'
  )

Partial Dependence Plots

A partial dependence plot (PDP) shows the marginal effect of one feature on the model output, averaged over all other features. It reveals whether the relationship is linear, monotonic, or has non-linear patterns. Use the pdp package or SHAPforxgboost::pdp_shap().

library(pdp)

# Partial dependence for 'lstat' in the Boston housing model
# We need a predict function wrapper for ranger
rf <- ranger(medv ~ ., data = MASS::Boston, num.trees = 300)

pd <- partial(
  rf,
  pred.var = 'lstat',
  train    = MASS::Boston,
  type     = 'regression'
)

plot(pd, type = 'l', lwd = 2,
     xlab = 'lstat', ylab = 'Partial Dependence',
     main = 'PDP: lstat vs medv')

SHAP Dependence Plot

A SHAP dependence plot shows the SHAP value for one feature plotted against its actual value. It is similar to a PDP but uses exact SHAP attributions and can colour points by a second interacting feature, revealing interaction effects.

library(shapviz)

shp <- shapviz(model, X_pred = X)

# SHAP dependence plot for 'lstat', coloured by 'rm'
sv_dependence(
  shp,
  v       = 'lstat',   # main feature on x-axis
  color_var = 'rm'     # interaction feature for colour
)

vip Package — Unified Importance

The vip package provides a model-agnostic importance interface that works with ranger, XGBoost, and any parsnip model. vip(model) creates a bar chart; vi(model) returns the importance values as a tibble.

library(vip)

# Works with parsnip fitted models
lm_fit <- fit(
  linear_reg() |> set_engine('lm'),
  medv ~ ., data = MASS::Boston
)

vip(lm_fit, num_features = 10)

# Also works with ranger directly
vip(rf_imp, num_features = 10)

# Return importance as a data frame
vi(rf_imp)

Quick Check

In XGBoost feature importance, which metric is generally considered the most informative for understanding feature quality?

Interpretation Recap

Key takeaways from Feature Importance and Model Interpretation:

  • xgb.importance(model) returns Gain, Cover, and Frequency; Gain is most informative.
  • xgb.plot.importance(imp) creates a bar chart of XGBoost importance.
  • ranger supports 'impurity' (fast) and 'permutation' (reliable) importance.
  • SHAP values decompose each prediction into per-feature contributions.
  • shapviz provides waterfall, beeswarm, and dependence plots for SHAP.
  • Partial dependence plots show the average marginal effect of each feature.
  • The vip package provides a model-agnostic unified importance interface.
library(shapviz)

# Complete interpretation workflow
shp <- shapviz(xgb_model, X_pred = X_matrix)

# 1. Global importance
sv_importance(shp, kind = 'beeswarm')

# 2. Local explanation for one observation
sv_waterfall(shp, row_id = 42)

# 3. Feature relationship
sv_dependence(shp, v = 'most_important_feature')

Frequently asked questions

Is the “Feature Importance and Model Interpretation” lesson free?

Yes — the full text of “Feature Importance and Model Interpretation” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.

What will I learn in “Feature Importance and Model Interpretation”?

Extract and visualize variable importance and SHAP values from ensemble models. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start R Academy?

No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Feature Importance and Model Interpretation” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this R Academy lesson?

Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Decision Trees: Foundation of Ensembles
  2. Random Forests with ranger
  3. Gradient Boosting with xgboost
  4. Feature Importance and Model Interpretation
← Back to R Academy