Introduction

Learning analytics is the use of data to understand and improve learning. Unsupervised learning is a type of machine learning that can be used to identify patterns and relationships in data without the need for labeled data.

In this case study, you will use unsupervised learning to analyze learning data from a Simulated School course. You will use dimensionality reduction to reduce the number of features in the data, and then use clustering to identify groups of students with similar learning patterns.

Data

The data for this case study is generated with the simulated function below. The data contains the following features:

Student ID: A unique identifier for each student Feature 1: A measure of student engagement Feature 2: A measure of student performance

simulate_student_features <- function(n = 100) {
  # Set the random seed
  set.seed(260923)
  
  # Generate unique student IDs
  student_ids <- seq(1, n)

  # Simulate student engagement
  student_engagement <- rnorm(n, mean = 50, sd = 10)

  # Simulate student performance
  student_performance <- rnorm(n, mean = 60, sd = 15)

  # Combine the data into a data frame
  student_features <- data.frame(
    student_id = student_ids,
    student_engagement = student_engagement,
    student_performance = student_performance
  )

  # Return the data frame
  return(student_features)
}

This function takes the number of students to simulate as an input and returns a data frame with three columns: student_id, student_engagement, and student_performance. The student_engagement and student_performance features are simulated using normal distributions with mean values of 50 and 60, respectively, and standard deviations of 10 and 15, respectively.

To use the simulate_student_features() function, we can simply pass the desired number of students to simulate as the argument:

student_features <- simulate_student_features(n = 100)

We can then use this data frame to perform unsupervised learning to identify groups of students with similar learning patterns,

Tasks

student_features <- simulate_student_features(n = 100)
head(student_features)
##   student_id student_engagement student_performance
## 1          1           35.47855            50.52231
## 2          2           51.79512            58.88396
## 3          3           62.41012            40.56755
## 4          4           35.20679            62.46033
## 5          5           59.37552            54.69326
## 6          6           57.00109            54.09745
# Perform PCA
pca_result <- prcomp(student_features[, -1], center = TRUE, scale. = TRUE)

# View the summary of the PCA result
summary(pca_result)
## Importance of components:
##                           PC1    PC2
## Standard deviation     1.0104 0.9895
## Proportion of Variance 0.5104 0.4896
## Cumulative Proportion  0.5104 1.0000
# Plot the explained variance
explained_variance <- pca_result$sdev^2 / sum(pca_result$sdev^2)
ggplot(data = data.frame(Principal_Component = 1:length(explained_variance), Explained_Variance = explained_variance), aes(x = Principal_Component, y = Explained_Variance)) +
  geom_line() +
  ggtitle("Explained Variance by Principal Components") +
  xlab("Principal Component") +
  ylab("Proportion of Variance Explained")

# Plot the PCA result
ggplot(data = as.data.frame(pca_result$x), aes(x = PC1, y = PC2)) +
  geom_point() +
  ggtitle("PCA of Student Features") +
  xlab("Principal Component 1") +
  ylab("Principal Component 2")

Clustering the Data : K-Means Clustering

The below K-Means algorithm divided the students into 3 clusters based on their engagement and performance. By examining the mean and standard deviation of these features within each cluster, we can infer the general characteristics of the students in each group.

# Perform K-Means clustering
set.seed(123)
kmeans_result <- kmeans(pca_result$x[, 1:2], centers = 3)

# Add the cluster assignments to the data
student_features$cluster <- kmeans_result$cluster

# Create a data frame for the PCA results and add cluster assignments
pca_df <- as.data.frame(pca_result$x[, 1:2])
colnames(pca_df) <- c("PC1", "PC2")
pca_df$cluster <- as.factor(kmeans_result$cluster)

# Create a data frame for the K-Means centers and name the columns
centers_df <- as.data.frame(kmeans_result$centers)
colnames(centers_df) <- c("PC1", "PC2")

# View the first few rows of the data with the cluster assignments
head(student_features)
##   student_id student_engagement student_performance cluster
## 1          1           35.47855            50.52231       2
## 2          2           51.79512            58.88396       3
## 3          3           62.41012            40.56755       3
## 4          4           35.20679            62.46033       2
## 5          5           59.37552            54.69326       3
## 6          6           57.00109            54.09745       3
# Plot the clusters
ggplot(pca_df, aes(x = PC1, y = PC2, color = cluster)) +
  geom_point() +
  geom_point(data = centers_df, aes(x = PC1, y = PC2), color = "red", size = 3, shape = 8) +
  ggtitle("K-means Clustering of Student Features") +
  xlab("Principal Component 1") +
  ylab("Principal Component 2")

-Clustering using DBSCAN

The below DBSCAN algorithm also grouped students based on their engagement and performance. This method is particularly effective at identifying clusters of varying shapes and sizes and handling noise in the data.

# Determine epsilon using kNN distance plot
dbscan::kNNdistplot(pca_result$x[, 1:2], k = 5)
abline(h = 2.1, col = "red")

# Perform DBSCAN clustering
set.seed(123)
dbscan_result <- dbscan(pca_result$x[, 1:2], eps = 2.1, minPts = 5)

# Add the cluster assignments to the data
student_features$dbscan_cluster <- dbscan_result$cluster

# View the first few rows of the data with the DBSCAN cluster assignments
head(student_features)
##   student_id student_engagement student_performance cluster dbscan_cluster
## 1          1           35.47855            50.52231       2              1
## 2          2           51.79512            58.88396       3              1
## 3          3           62.41012            40.56755       3              1
## 4          4           35.20679            62.46033       2              1
## 5          5           59.37552            54.69326       3              1
## 6          6           57.00109            54.09745       3              1
# Plot the DBSCAN clusters
ggplot(data = as.data.frame(pca_result$x), aes(x = PC1, y = PC2, color = as.factor(dbscan_result$cluster))) +
  geom_point() +
  ggtitle("DBSCAN Clustering of Student Features") +
  xlab("Principal Component 1") +
  ylab("Principal Component 2")

# Summary of K-Means clustering results
kmeans_summary <- student_features %>%
  group_by(cluster) %>%
  summarize(across(c(student_engagement, student_performance), list(mean = mean, sd = sd)))

print(kmeans_summary)
## # A tibble: 3 × 5
##   cluster student_engagement_mean student_engagement_sd student_performance_mean
##     <int>                   <dbl>                 <dbl>                    <dbl>
## 1       1                    48.7                  7.30                     76.1
## 2       2                    41.2                  7.94                     52.0
## 3       3                    59.6                  5.32                     57.4
## # ℹ 1 more variable: student_performance_sd <dbl>
# Summary of DBSCAN clustering results
dbscan_summary <- student_features %>%
  group_by(dbscan_cluster) %>%
  summarize(across(c(student_engagement, student_performance), list(mean = mean, sd = sd)))

print(dbscan_summary)
## # A tibble: 1 × 5
##   dbscan_cluster student_engagement_mean student_engagement_sd
##            <int>                   <dbl>                 <dbl>
## 1              1                    50.4                  10.1
## # ℹ 2 more variables: student_performance_mean <dbl>,
## #   student_performance_sd <dbl>

Submission

Submit a report containing the following:

Your report should include your code. Submit the published RPubs link to Blackboard.