library(car)
library(jsonlite)
convert_categorical_to_numeric <- function(data, dataset_name) {
non_numeric_cols <- names(data)[sapply(data, function(x) !is.numeric(x))]
if (length(non_numeric_cols) > 0) {
cat(paste0("INFO: Dataset '", dataset_name, "' contains non-numeric columns: ",
paste(non_numeric_cols, collapse = ", "), "\n"))
cat("Converting categorical variables to numeric representations...\n")
for (col in non_numeric_cols) {
if (is.factor(data[[col]])) {
unique_vals <- length(unique(data[[col]]))
data[[col]] <- as.numeric(data[[col]])
cat(paste0(" ", col, ": ", unique_vals, " unique values -> integer level encoding\n"))
} else if (is.character(data[[col]])) {
unique_vals <- length(unique(data[[col]]))
temp_numeric <- as.numeric(data[[col]])
if (any(is.na(temp_numeric))) {
data[[col]] <- as.numeric(as.factor(data[[col]]))
cat(paste0(" ", col, ": ", unique_vals, " unique values -> integer level encoding\n"))
} else {
data[[col]] <- temp_numeric
cat(paste0(" ", col, ": ", unique_vals, " unique values -> numeric encoding\n"))
}
}
}
}
return(data)
}
args <- commandArgs(trailingOnly = TRUE)
default_csv <- "../../datasets/csv/mtcars.csv"
default_output <- "../../results/r"
csv_path <- ifelse(length(args) >= 1, args[1], default_csv)
output_dir <- ifelse(length(args) >= 2, args[2], default_output)
if (!file.exists(csv_path)) {
stop(paste("CSV file not found:", csv_path))
}
dataset_name <- tools::file_path_sans_ext(basename(csv_path))
data <- read.csv(csv_path)
data <- convert_categorical_to_numeric(data, dataset_name)
response_col <- names(data)[1]
predictor_cols <- names(data)[-1]
if (length(predictor_cols) < 2) {
cat(paste0("SKIP: Dataset '", dataset_name, "' has only ", length(predictor_cols),
" predictor. VIF requires at least 2 predictors.\n"))
quit(status = 0)
}
formula_str <- paste(response_col, "~", paste(predictor_cols, collapse = " + "))
formula <- as.formula(formula_str)
model <- lm(formula, data = data)
vif_result <- car::vif(model)
cat("VIF Test (R - car::vif)\n")
cat("=================================\n")
cat("Dataset:", dataset_name, "\n")
cat("Formula:", formula_str, "\n")
cat("Number of predictors:", length(vif_result), "\n\n")
cat("VIF Results:\n")
for (i in 1:length(vif_result)) {
cat(sprintf(" %s: VIF = %.6f, R² = %.6f\n",
names(vif_result)[i],
as.numeric(vif_result[i]),
1 - 1/as.numeric(vif_result[i])))
}
cat(sprintf("\nMax VIF: %.6f\n\n", max(as.numeric(vif_result))))
max_vif <- max(as.numeric(vif_result))
if (max_vif > 10) {
interpretation <- "Severe multicollinearity detected (VIF > 10)"
} else if (max_vif > 5) {
interpretation <- "Moderate multicollinearity detected (VIF > 5)"
} else {
interpretation <- "Low multicollinearity (VIF ≤ 5)"
}
cat("Interpretation:", interpretation, "\n\n")
output <- list(
test_name = "VIF Test (R - car::vif)",
dataset = dataset_name,
formula = formula_str,
vif_results = as.data.frame(vif_result),
vif_numeric = as.numeric(vif_result),
max_vif = max_vif,
interpretation = interpretation,
description = "Variance Inflation Factor measures multicollinearity among predictors. Uses car::vif()."
)
if (!dir.exists(output_dir)) {
dir.create(output_dir, recursive = TRUE)
}
output_file <- file.path(output_dir, paste0(dataset_name, "_vif.json"))
write_json(output, output_file, pretty = TRUE, digits = 22)
cat("Results saved to:", output_file, "\n")