Skip to Content
Course content

211: Feature Importance Analysis in R

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent a lot of time building models that have great accuracy on a test set, only to have a stakeholder ask me: "Okay, it works, but why is it saying this specific customer is going to leave?" That's where we hit the "black box" problem. If you're using a complex model like a Random Forest, you can't just look at a coefficient like you do in a linear regression. You need a way to extract feature importance.

The Black Box Problem

Let's look at a scenario I'm dealing with right now. I have a dataset of customer churn—basically, trying to predict if a user will cancel their subscription. I've already got a Random Forest model running, but it's just giving me "Yes" or "No" without any explanation. I want to know if it's the monthly price, the length of the contract, or maybe just how many support tickets they've opened that's driving the prediction.

library(randomForest)

# I'll whip up a quick dataset for us to play with
set.seed(42)
churn_data <- data.frame(
  tenure = rnorm(100, 20, 5),
  monthly_charges = rnorm(100, 70, 15),
  support_calls = sample(0:10, 100, replace = TRUE),
  contract_type = as.factor(sample(c("Month-to-Month", "One Year", "Two Year"), 100, replace = TRUE)),
  churn = as.factor(sample(c("Yes", "No"), 100, replace = TRUE))
)

# Training a basic model
rf_model <- randomForest(churn ~ ., data = churn_data, importance = TRUE)
print(rf_model)

If I just print the model, I see the error rate, but nothing about the features. I remembered to set importance = TRUE in the function call—if you forget that, R won't bother calculating the importance metrics during the training process, and you'll be stuck staring at an empty result.

Digging into the Forest

Now, I'll try to actually pull those importance values out. The randomForest package has a dedicated function for this.

imp_values <- importance(rf_model)
print(imp_values)

When I run this, I get a matrix with two columns: MeanDecreaseAccuracy and MeanDecreaseGini. This is where it gets confusing. At first glance, they look similar, but they're measuring different things. I often see people just grab the first column and call it a day, but that's a mistake.

The Gini importance (Mean Decrease Gini) is basically measuring how much each variable contributes to the "purity" of the nodes in the trees. It's fast to calculate, but here's the catch: it's heavily biased toward variables with many possible values (high cardinality). If I had a "Customer ID" column in here, Gini would probably tell me it's the most important feature, which is completely useless for actual analysis.

Gini vs. Accuracy: Which one to trust?

To see if the results differ, I'll plot them side-by-side. I prefer a visual representation because looking at a matrix of numbers is a great way to miss a trend.

# Converting to a data frame for easier plotting
imp_df <- as.data.frame(imp_values)
rownames(imp_df) <- row.names(imp_df)
imp_df$Feature <- rownames(imp_df)

# Let's just look at the Accuracy column for a moment
barplot(imp_df$MeanDecreaseAccuracy, 
        names.arg = imp_df$Feature, 
        main = "Feature Importance (Accuracy)", 
        col = "steelblue", 
        las = 2)

The MeanDecreaseAccuracy is more reliable. It works by randomly permuting the values of a feature and seeing how much the model's accuracy drops. If the accuracy tanks when I shuffle "contract_type," then that feature was doing a lot of heavy lifting. If shuffling "support_calls" doesn't change anything, that feature is basically noise.

Cleaning up the noise with caret

While the base randomForest output is fine, I usually find it a bit clunky for reporting. If you're working in a professional pipeline, I recommend the caret package. It provides a standardized varImp function that works across almost any model type—whether it's a GLM, a Random Forest, or an SVM.

library(caret)
importance_caret <- varImp(rf_model)
plot(importance_caret)

Notice how caret scales the importance from 0 to 100. This is much more intuitive when you're presenting your findings to someone who isn't a data scientist. Instead of saying "The Mean Decrease Accuracy was 0.12," you can say "This feature accounts for 80% of the relative importance compared to other variables." It's a small change, but it makes the communication much smoother.




📋 Practical Task

Exercise: Identifying the Main Drivers of Customer Churn

Using the randomForest and caret packages, complete the following task:

  1. Create a synthetic dataset with 200 observations and four features: usage_hours (numeric), monthly_fee (numeric), customer_age (numeric), and region (factor). Create a target variable will_churn (factor: "Yes"/"No").
  2. Train a Random Forest model to predict will_churn, ensuring that the importance calculation is enabled.
  3. Use the varImp function from the caret package to calculate the feature importance.
  4. Generate a plot of the importance values and identify which of the four features is the most influential in the model's decision-making process.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.