Title: ECI 587: Introduction to Learning Analytics Output: HTML (default is fine)
install.packages(“tidyverse”) install.packages(“caret”) install.packages(“randomForest”) install.packages(“scales”) install.packages(“ggplot2”) install.packages(“dplyr”)
library(“tidyverse”) library(“caret”) library(“randomForest”) library(“scales”) library(“ggplot2”) library(“stringr”) library(dplyr)
set.seed(42)
library(readr) library(tidyverse)
df <- read_csv(“students.csv”)
glimpse(df)
getwd() list.files()
summary(df)
colSums(is.na(df))
sum(duplicated(df))
df <- df %>% mutate( Gender = as.factor(Gender), Branch =
as.factor(Branch), Internship_Done =
as.factor(Internship Done) )
df_cleaned <- df %>% select( -Student ID, -Name,
-Placement Status, -CTC (LPA),
-Alumni Path, -Internship Domain, )
df_cleaned <- df_cleaned %>% mutate( Clubs = ifelse(is.na(Clubs), ““, Clubs), Skills = ifelse(is.na(Skills),”“, Skills) )
df_cleaned <- df_cleaned %>% mutate( Has_Clubs = ifelse(Clubs == ““, 0, 1) )
df_cleaned <- df_cleaned %>% mutate( Knows_Python = ifelse(str_detect(Skills, regex(“Python”, ignore_case = TRUE)), 1, 0), Knows_C = ifelse(str_detect(Skills, regex(“C\+\+”, ignore_case = TRUE)), 1, 0), Knows_ML = ifelse(str_detect(Skills, regex(“Machine Learning”, ignore_case = TRUE)), 1, 0), Knows_Java = ifelse(str_detect(Skills, regex(“Java”, ignore_case = TRUE)), 1, 0), Knows_SQL = ifelse(str_detect(Skills, regex(“SQL”, ignore_case = TRUE)), 1, 0), Knows_WD = ifelse(str_detect(Skills, regex(“Web Development”, ignore_case = TRUE)), 1, 0), Knows_DS = ifelse(str_detect(Skills, regex(“Data Science”, ignore_case = TRUE)), 1, 0)
colnames(df_cleaned)
df_cleaned <- df_cleaned %>%
mutate(
Internship_Done_Binary = ifelse(`Internship Done` == "Yes", 1, 0),
Skill_Count = ifelse(Skills == "", 0, str_count(Skills, ",") + 1)
)
df_cleaned <- df_cleaned %>%
mutate(
Avg_Sem_GPA = rowMeans(select(., starts_with("Sem")), na.rm = TRUE),
Sem_GPA_SD = apply(select(., starts_with("Sem")), 1, sd, na.rm = TRUE)
)
# Step 3: Train/Test Split in R
df_model <- df_cleaned %>%
filter(!is.na(Internship_Done_Binary))
# 3.1 Define outcome variable
y <- df_cleaned$Internship_Done_Binary
table(y)
y <- factor(y, levels = c(0, 1))
# 3.2 Define predictor variables
predictors <- df_cleaned %>%
select(
Gender, Branch, Age,
`Average GPA`, Backlogs, `Attendance (%)`,
Has_Clubs, Skill_Count,
Knows_Python, Knows_CPP, Knows_ML,
Avg_Sem_GPA, Sem_GPA_SD,
starts_with("Sem")
)
# 3.3 Create Train/Test Split
train_index <- createDataPartition(y, p = 0.75, list = FALSE)
X_train <- predictors[train_index, ]
X_test <- predictors[-train_index, ]
y_train <- y[train_index]
y_test <- y[-train_index]
# 3.4 Confirm split
cat("Training rows:", nrow(X_train), "\n")
cat("Testing rows:", nrow(X_test), "\n")
## Step 4: Logistic Regression
# Make sure outcome is numeric 0/1 (or factor with 0/1)
y_train_glm <- as.numeric(as.character(y_train)) # in case it's factor
log_data <- data.frame(
Internship_Done_Binary = y_train_glm,
X_train
)
log_model <- glm(
Internship_Done_Binary ~ .,
data = log_data,
family = binomial
)
# Predict probabilities on test set
log_test_data <- data.frame(X_test)
log_probs <- predict(log_model, newdata = log_test_data, type = "response")
# Convert probabilities to class labels (0/1)
log_pred_class <- ifelse(log_probs > 0.5, 1, 0)
# Make sure both are factors with same levels
log_pred_factor <- factor(log_pred_class, levels = c(0, 1))
y_test_factor <- factor(y_test, levels = c(0, 1))
confusionMatrix(log_pred_factor, y_test_factor, positive = "1")
summary(log_model)
## Step 5: Random Forest
# Check for NAs in predictors
colSums(is.na(X_train))
# 5.1 Make outcome a factor first
y_train_rf <- factor(y_train, levels = c(0, 1))
# 5.2 Keep only complete cases in training predictors
train_complete <- complete.cases(X_train)
X_train_rf <- X_train[train_complete, ]
y_train_rf_clean <- y_train_rf[train_complete]
# 5.3 Fit Random Forest model
rf_model <- randomForest(
x = X_train_rf,
y = y_train_rf_clean,
ntree = 500,
importance = TRUE
)
rf_model
# 5.4 Clean test set to remove NAs in predictors
test_complete <- complete.cases(X_test)
X_test_rf <- X_test[test_complete, ]
y_test_rf <- y_test[test_complete]
# 5.5 Predict on test set
rf_pred <- predict(rf_model, newdata = X_test_rf)
# 5.6 Evaluate performance
confusionMatrix(
rf_pred,
factor(y_test_rf, levels = c(0, 1)),
positive = "1"
)
test_complete <- complete.cases(X_test)
X_test_rf <- X_test[test_complete, ]
y_test_rf <- y_test[test_complete]
rf_pred <- predict(rf_model, newdata = X_test_rf)
confusionMatrix(rf_pred, factor(y_test_rf, levels = c(0, 1)), positive = "1")
ggplot(df_cleaned, aes(x = Gender, fill = factor(`Internship Done`))) +
geom_bar(position = "dodge") +
scale_fill_manual(
values = c("No" = "blue", "Yes" = "red"),
labels = c("No Internship", "Completed Internship")
) +
labs(
title = "Internship Completion Count by Gender",
x = "Gender",
y = "Count of Students",
fill = "Internship Status"
) +
theme_minimal()
ggplot(df_cleaned, aes(x = Branch, fill = factor(`Internship Done`))) +
geom_bar(position = "dodge") +
scale_fill_manual(
values = c("No" = "tomato", "Yes" = "steelblue"),
labels = c("No Internship", "Completed Internship")
) +
labs(
title = "Internship Completion by Engineering Academic Major",
x = "Major (Branch)",
y = "Count of Students",
fill = "Internship Status"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
ggplot(df_cleaned, aes(x = factor(Backlogs), fill = factor(`Internship Done`))) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent_format()) +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Internship Completion Rate by Number of Backlogs",
x = "Backlogs",
y = "Proportion of Students",
fill = "Internship Status"
) +
theme_minimal()
df_att <- df_cleaned |> tidyr::drop_na(`Attendance (%)`, `Internship Done`)
ggplot(df_att, aes(
x = factor(`Internship Done`, levels = c("No", "Yes")),
y = `Attendance (%)`
)) +
geom_boxplot(fill = "lightgreen") +
labs(
title = "Attendance Rates by Internship Completion",
x = "Internship Completed",
y = "Attendance (%)"
) +
theme_minimal()
df_clubs <- df_cleaned |>
dplyr::filter(!is.na(Has_Clubs), !is.na(`Internship Done`))
ggplot(df_clubs, aes(x = factor(Has_Clubs), fill = factor(`Internship Done`))) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent_format()) +
scale_fill_manual(
values = c("No" = "#FF6F61", "Yes" = "#6B5B95"),
labels = c("No Internship", "Completed Internship")
) +
labs(
title = "Internship Completion Rate by Club Involvement",
x = "Club Involvement (0 = No, 1 = Yes)",
y = "Proportion of Students",
fill = "Internship Status"
) +
theme_minimal()
ggplot(df_cleaned, aes(x = Branch)) +
geom_bar(fill = "red") +
labs(
title = "Number of Students by Major",
x = "Major (Branch)",
y = "Count"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
df_cleaned$Knows_Python <- ifelse(grepl("Python", df_cleaned$Skills, ignore.case = TRUE), 1, 0)
df_cleaned$Knows_C <- ifelse(grepl("C\\+\\+", df_cleaned$Skills, ignore.case = TRUE), 1, 0)
df_cleaned$Knows_ML <- ifelse(grepl("Machine Learning", df_cleaned$Skills, ignore.case = TRUE), 1, 0)
df_cleaned$Knows_Java <- ifelse(grepl("Java", df_cleaned$Skills, ignore.case = TRUE), 1, 0)
df_cleaned$Knows_SQL <- ifelse(grepl("SQL", df_cleaned$Skills, ignore.case = TRUE), 1, 0)
df_cleaned$Knows_WD <- ifelse(grepl("Web Development", df_cleaned$Skills, ignore.case = TRUE), 1, 0)
df_cleaned$Knows_DS <- ifelse(grepl("Data Science", df_cleaned$Skills, ignore.case = TRUE), 1, 0)
names(df_cleaned)
skills <- c("Knows_Python", "Knows_C", "Knows_ML",
"Knows_Java", "Knows_SQL", "Knows_WD", "Knows_DS")
skill_labels <- c(
Knows_Python = "Python",
Knows_C = "C++",
Knows_ML = "Machine Learning",
Knows_Java = "Java",
Knows_SQL = "SQL",
Knows_WD = "Web Development",
Knows_DS = "Data Science"
)
all_skill_results <- list()
for (s in skills) {
sub <- df_cleaned[df_cleaned[[s]] == 1, ]
if (nrow(sub) == 0) next
tab <- prop.table(table(sub[["Internship Done"]]))
all_skill_results[[s]] <- data.frame(
Skill = skill_labels[[s]],
InternshipStatus = names(tab),
Proportion = as.numeric(tab)
)
}
skill_summary <- do.call(rbind, all_skill_results)
ggplot(skill_summary,
aes(x = Skill,
y = Proportion,
fill = factor(InternshipStatus))) +
geom_col() +
scale_y_continuous(labels = percent_format()) +
coord_flip() +
labs(
title = "Internship Completion Rate by Skill",
x = "Skill",
y = "Proportion of Students (who have that skill)",
fill = "Internship Status"
) +
theme_minimal()
ls()
library(ggplot2)
library(scales)
ggplot(skill_summary,
aes(x = Skill,
y = Proportion,
fill = factor(InternshipStatus))) +
geom_col() +
scale_y_continuous(labels = percent_format()) +
coord_flip() +
labs(
title = "Internship Completion Rate by Skill",
x = "Skill",
y = "Proportion of Students (who have that skill)",
fill = "Internship Status"
) +
theme_minimal()