This regression project aims to predict customers’
TotalCharges based on multiple telecom service features
using Random Forest and Gradient Boosting (GBM) models. The goal is to
evaluate predictive accuracy and identify the most influential
variables.
| Step | Process | Description |
|---|---|---|
| 1 | Load libraries | Load necessary R packages for modeling and visualization |
| 2 | Load and clean data | Read dataset, filter missing/invalid rows, and process categorical features |
| 3 | Feature engineering | Remove irrelevant features and create a numeric support feature
(NS) |
| 4 | Data splitting | Split dataset into training and testing sets (70:30) |
| 5 | Model training | Train Random Forest and GBM regression models |
| 6 | Model evaluation | Compute RMSE, R², and MAE for both models |
| 7 | Feature importance | Plot top 15 most important variables from Random Forest |
| 8 | Visualization | Plot predicted vs actual TotalCharges for each model |
| 9 | Export results | Save outputs: plots, CSV files, RDS model |
library(dplyr)
library(caret)
library(randomForest)
library(ggplot2)
library(corrplot)
set.seed(123)
out_dir <- "Regression_Results"
if (!dir.exists(out_dir)) dir.create(out_dir)
f <- "customer_churn_telecom_services.csv"
df <- read.csv(f)
prep <- function(df) {
df <- df[df$TotalCharges != "" & !is.na(df$TotalCharges), ]
df$TotalCharges <- as.numeric(as.character(df$TotalCharges))
cat_vars <- c("gender", "Partner", "Dependents", "PhoneService",
"MultipleLines", "InternetService", "OnlineSecurity",
"OnlineBackup", "DeviceProtection", "TechSupport",
"StreamingTV", "StreamingMovies", "Contract",
"PaperlessBilling", "PaymentMethod", "Churn")
for (v in cat_vars) {
df[[v]] <- factor(df[[v]])
levels(df[[v]]) <- gsub("No internet service|No phone service", "No", levels(df[[v]]))
}
df <- df %>% select(-MonthlyCharges, -Churn)
df$NS <- rowSums(df %>% select(OnlineSecurity, OnlineBackup, DeviceProtection,
TechSupport, StreamingTV, StreamingMovies) == "Yes")
df <- df %>%
mutate(TotalCharges = ifelse(tenure == 0 & TotalCharges > 0, TotalCharges, TotalCharges))
return(df)
}
df_c <- prep(df)
idx <- createDataPartition(df_c$TotalCharges, p = 0.7, list = FALSE)
trn <- df_c[idx, ]
tst <- df_c[-idx, ]
mdl_list <- list()
res <- list()
eval_m <- function(m, tst) {
pred <- predict(m, newdata = tst)
rmse <- RMSE(pred, tst$TotalCharges)
r2 <- R2(pred, tst$TotalCharges)
mae <- MAE(pred, tst$TotalCharges)
return(list(pred = pred, metrics = data.frame(RMSE = rmse, R2 = r2, MAE = mae)))
}
set.seed(123)
mdl_list[["RF"]] <- randomForest(TotalCharges ~ ., data = trn, ntree = 200)
res[["RF"]] <- eval_m(mdl_list[["RF"]], tst)
set.seed(123)
ctrl <- trainControl(method = "cv", number = 5)
mdl_list[["GBM"]] <- train(TotalCharges ~ ., data = trn, method = "gbm", trControl = ctrl, verbose = FALSE)
res[["GBM"]] <- eval_m(mdl_list[["GBM"]], tst)
imp <- varImp(mdl_list[["RF"]], scale = TRUE)
imp_df <- data.frame(Var = rownames(imp), Imp = imp$Overall) %>% arrange(desc(Imp))
p_imp <- imp_df %>%
head(15) %>%
ggplot(aes(x = reorder(Var, Imp), y = Imp)) +
geom_col(fill = "steelblue") +
coord_flip() +
labs(title = "Top 15 Important Features", x = "Variables", y = "Importance") +
theme_minimal()
ggsave(file.path(out_dir, "feature_importance.png"), p_imp, width = 8, height = 6)
plot_cmp <- function(tst, res) {
df_all <- data.frame()
for (m in names(res)) {
df_temp <- data.frame(Model = m,
Actual = tst$TotalCharges,
Predicted = res[[m]]$pred)
df_all <- rbind(df_all, df_temp)
}
ggplot(df_all, aes(x = Actual, y = Predicted)) +
geom_point(alpha = 0.3, color = "steelblue") +
geom_abline(slope = 1, intercept = 0, color = "red", linetype = "dashed") +
facet_wrap(~ Model, ncol = 2) +
labs(title = "Actual vs Predicted Values",
x = "Actual Total Charges", y = "Predicted Total Charges") +
theme_bw()
}
p_cmp <- plot_cmp(tst, res)
ggsave(file.path(out_dir, "predictions_vs_actual.png"), p_cmp, width = 10, height = 8)
m_df <- data.frame()
for (m in names(res)) {
m_df <- rbind(m_df, data.frame(Model = m, res[[m]]$metrics))
}
write.csv(m_df, file.path(out_dir, "model_performance.csv"), row.names = FALSE)
saveRDS(mdl_list, file.path(out_dir, "regression_models.rds"))
write.csv(df_c, file.path(out_dir, "cleaned_dataset.csv"), row.names = FALSE)
print("Model Comparison:")
## [1] "Model Comparison:"
print(m_df)
## Model RMSE R2 MAE
## 1 RF 157.4967 0.9957800 105.41846
## 2 GBM 138.5160 0.9962581 98.31762
cat("\nResults saved in:", out_dir)
##
## Results saved in: Regression_Results