-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGradePredictionMain.Rmd
More file actions
257 lines (199 loc) · 8.59 KB
/
GradePredictionMain.Rmd
File metadata and controls
257 lines (199 loc) · 8.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
---
title: "Predict Student's Final Grade"
output:
html_document:
df_print: paged
---
<h2>
Created for the <a href="https://sites.google.com/ncsu.edu/csedm-dc-2021/home">2nd CSEDM Data Challenge</a>
</h2>
<h3>
Installing libraries
</h3>
<p>This step is only necessary the first time the file is run on a machine.</p>
```{r}
# install.packages("tidyverse")
# install.packages("BBmisc")
# install.packages("caret")
# install.packages("ggvis")
#install.packages("randomForest")
#install.packages("caTools")
```
<h3> Importing libraries </h3>
```{r, message=FALSE}
library(tidyverse)
library(BBmisc)
library(caret)
library(ggvis)
library(randomForest)
library(caTools)
```
<h3>Loading All Data</h3>
<p>personal_path will need to be changed to match local machine filepath</p>
```{r, message=FALSE}
personal_path <- "/Users/katiepell/school/cs496"
base_dir <- "cs496-csedm-main"
train_path <- "S19_Release_6_28_21.zip/Train" # Path to training data
test_path <- "S19_Release_6_28_21.zip/Test" # Path to testing data
subject_path <- "Data/LinkTables/Subject.csv"
early_path <- "early.csv"
late_path <- "late.csv"
train_id_grade_path <- paste(personal_path, base_dir, train_path, subject_path, sep="/")
test_id_grade_path <- paste(personal_path, base_dir, test_path, subject_path, sep="/")
train_id_grade_data <- read_csv(train_id_grade_path)
test_id_grade_data <- read_csv(test_id_grade_path)
train_early_path <- paste(personal_path, base_dir, train_path, early_path, sep = "/")
test_early_path <- paste(personal_path, base_dir, test_path, early_path, sep = "/")
train_early_data <- read_csv(train_early_path)
test_early_data <- read_csv(test_early_path)
train_late_path <- paste(personal_path, base_dir, train_path, late_path, sep = "/")
test_late_path <- paste(personal_path, base_dir, test_path, late_path, sep = "/")
train_late_data <- read_csv(train_late_path)
test_late_data <- read_csv(test_late_path)
```
<p>Function to find each student's average number of attempts</p>
```{r, message=FALSE}
find_avg_attempts = function(student_instance, early_dataset){
# This is get the all data related to the current student
first_half_data <- filter(early_dataset, SubjectID == student_instance)
# find avg number of attempts
avg_attempts <- median(first_half_data$Attempts)
}
```
```{r, message=FALSE}
# Function to find each student's percent correct eventually
find_percent_CorrectEventually = function(student_instance, early_dataset){
# This is get the all data related to the current student
first_half_data <- filter(early_dataset, SubjectID == student_instance) # All of this student's problem entries from the the early part of the semester
# find percent of time student gets the right answer eventually
PerCorrectEventually <- mean(first_half_data$CorrectEventually) # Average number correct for all of this student's problems that are attempted
}
```
<p>
Feature Extraction on the training data
</p>
```{r, message=FALSE}
# ***** I THINK THIS NEEDS TO BE "MERGED" WITH THE APPROPRIATE OTHER DATASET... *****
merged_data_train <- merge(train_id_grade_data, train_early_data, by= "SubjectID")
# Add a column with each student's average number of attempts
agg_train_id_grade_data <- merged_data_train %>%
rowwise() %>%
mutate(avg_attempts = find_avg_attempts(SubjectID, train_early_data))
# Add a column with each student's percent correct eventually
agg_train_id_grade_data <- agg_train_id_grade_data %>%
rowwise() %>%
mutate(per_CorrectEventually = find_percent_CorrectEventually(SubjectID, train_early_data))
```
```{r, message=FALSE}
# Change names for simplicity
names(agg_train_id_grade_data)[names(agg_train_id_grade_data) == "X-Grade"] <- "grade"
names(agg_train_id_grade_data)[names(agg_train_id_grade_data) == "SubjectID"] <- "id"
names(agg_train_id_grade_data)[names(agg_train_id_grade_data) == "AssignmentID"] <- "assignment_id"
names(agg_train_id_grade_data)[names(agg_train_id_grade_data) == "ProblemID"] <- "problem_id"
```
```{r, message=FALSE}
# Format test data similar to above format of training data
merged_data_test <- merge(test_id_grade_data, test_early_data, by= "SubjectID")
agg_test_id_grade_data <- merged_data_test %>% # Add the attempt column to the test data
rowwise() %>%
mutate(avg_attempts = find_avg_attempts(SubjectID, test_early_data))
agg_test_id_grade_data <- agg_test_id_grade_data %>% # Add the percentCorrect column to the test data
rowwise() %>%
mutate(per_CorrectEventually = find_percent_CorrectEventually(SubjectID, test_early_data))
```
```{r, message=FALSE}
# Change names for simplicity
names(agg_test_id_grade_data)[names(agg_test_id_grade_data) == "SubjectID"] <- "id"
names(agg_test_id_grade_data)[names(agg_test_id_grade_data) == "AssignmentID"] <- "assignment_id"
names(agg_test_id_grade_data)[names(agg_test_id_grade_data) == "ProblemID"] <- "problem_id"
```
<p>Linear Models</p>
```{r, message=FALSE}
# Avg_attempts vs. final grade
model1 <- lm(avg_attempts~grade, data=agg_train_id_grade_data)
#Percent eventually correct vs. final grade
model2 <- lm(per_CorrectEventually~grade, data = agg_train_id_grade_data)
# Percent eventually correct AND average attempts vs. final grade
model3 <- lm(grade~avg_attempts+per_CorrectEventually, data=agg_train_id_grade_data)
attempts_grade_plot <- agg_train_id_grade_data %>%
ggplot(aes(x = avg_attempts, y = grade)) +
geom_point() + geom_smooth(method="lm")
labs(x = "Average attempts", y = "Final grade")
percent_grade_plot <- agg_train_id_grade_data %>%
ggplot(aes(x = per_CorrectEventually, y = grade)) +
geom_point() + geom_smooth(method="lm")
labs(x = "Percent correct eventually", y = "Final grade")
s1 <- summary(model1)
s2 <- summary(model2)
s3 <- summary(model3)
s1$r.squared # Correlation between average attempts and final grade
s2$r.squared # Correlation between percent eventually correct and final grade
s3$r.squared # Correlation between both factors and final grade
```
```{r, message=FALSE}
# these scatter plots are colored to differentiate problem/assignment number
assignment_plot1 <- agg_train_id_grade_data %>% ggvis(~avg_attempts, ~grade, fill = ~assignment_id) %>% layer_points()
assignment_plot1
assignment_plot2 <- agg_train_id_grade_data %>% ggvis(~per_CorrectEventually, ~grade, fill = ~assignment_id) %>% layer_points()
assignment_plot2
problem_plot1 <- agg_train_id_grade_data %>% ggvis(~avg_attempts, ~grade, fill = ~problem_id) %>% layer_points()
problem_plot1
problem_plot2 <- agg_train_id_grade_data %>% ggvis(~per_CorrectEventually, ~grade, fill = ~problem_id) %>% layer_points()
problem_plot2
```
<p>Random Forest Regression Models</p>
```{r, message=FALSE}
# Create a random forest with the training data
rf_train_data <- agg_train_id_grade_data
rf_train_data$assignment_id = as.factor(rf_train_data$assignment_id) # Create assignment ID as a factor
rf_train_data$problem_id = as.factor(rf_train_data$problem_id) # Create problem ID as a factor
# summary(rf_train_data)
```
```{r, message=FALSE}
# Create a random forest with the testing data
rf_test_data <- agg_test_id_grade_data
rf_test_data$assignment_id = as.factor(rf_test_data$assignment_id)
rf_test_data$problem_id = as.factor(rf_test_data$problem_id)
# summary(rf_test_data)
```
```{r, message=FALSE}
# creating a random forest
head(rf_train_data)
sapply(rf_train_data, class)
summary(rf_train_data)
```
```{r, message=FALSE}
# Perform random forest regression on training data
rf_regression <- randomForest(grade ~ ., data = rf_train_data, ntree=500, mtry = 8, importance = TRUE, na.action = na.omit)
print(rf_regression)
# plot(rf_regression)
```
```{r, message=FALSE}
pred_rf <- predict(rf_regression, rf_test_data)
summary(pred_rf)
```
<p>Writing predictions to a file</p>
```{r, message=FALSE}
# This creates a new file called prediction.csv and writes the predicted grades to it
write.csv(pred_rf, "prediction.csv", row.names=FALSE)
# currently the column is titled 'x' and I can't figure out how to change that
```
```{r, message = FALSE}
end_data <- rf_test_data[,c('id')]
end_data['grade'] = pred_rf
end_data$Mean <- with(end_data, ave(end_data$grade, id, FUN=mean))
end_data <- subset(end_data, select = -c(grade))
unique_values <- end_data[!duplicated(end_data$id), ]
names(unique_values)[names(unique_values) == "id"] <- "SubjectID"
names(unique_values)[names(unique_values) == "Mean"] <- "X-Grade"
```
}
```{r}
# merge predictions with student id number and write to prediction.csv
write.csv(unique_values, 'predictions.csv', row.names = FALSE)
```
<h3>Troubleshooting</h3>
<p>
<b>Q:</b> I am getting an error that "assignment-id is not located in agg_train_id_grade_data"<br>
<b>A:</b> Confirm that the downloaded folder is named properly, "cs496-csedm-main".
</p>