## # A tibble: 5 x 2
## Teacher `Average Grade`
## <fct> <dbl>
## 1 Alan 52.9
## 2 Brindley 69.4
## 3 Devin 53.8
## 4 Madelyn 60.2
## 5 Suzana 61.0
blahblahblah
Generally, the first thing we want to look at in one of these analyses is the overall distribution of grades, which we can see in the histogram below.
#Single Histogram
#Histograms
ggplot(data=EoTTotals, aes(x=Percentage)) +
geom_histogram(aes(y=..density..), alpha = 0.6, position = "identity") +
labs(x="Grade (Percentage)", y="Density") +
stat_function(fun=dnorm, args = list(mean=mean(EoTTotals$Percentage), sd=sd(EoTTotals$Percentage)),
color="black", size = 1.4) +
scale_fill_manual(values= c("darkred", "darkgrey")) +
scale_x_continuous(limits = c(0,100)) +
theme_alan() +
ggtitle("Histogram of Grades in AS Global Perspectives End of Term Exams")
ggsave(here("EoT Histogram.png"), plot = last_plot(), device = NULL, path = NULL,
width = 8, height = 4, units = c("in", "cm", "mm"),
dpi = 600)
Overall performance was pretty poor, with an average score of 59.75% and a standard deviation of 17.4% (Range = 7% to 93%).
Lets see how the grades fell on a by-teacher basis.
EoTSummaryTeacher <- summarySE(EoTTotals, measurevar = "Percentage", groupvars = c("Teacher"))
ggplot(data=EoTSummaryTeacher, aes(x=Teacher, y= Percentage, fill = Teacher)) +
geom_bar(stat= "summary", position = pd, width = 0.8) +
geom_errorbar(aes(ymin= Percentage - se, ymax= Percentage + se), width= 0.2, size = 1, position= pd)+
#annotate("text", x=11.5, y=7.2, label = "Average Grades", hjust = 0, fontface = "bold") +
#annotate("text", x=11.5, y=6.7, label = "Alan's Class = 52.3%", hjust = 0, color = "darkred") +
#annotate("text", x=11.5, y=6.2, label = "June's Class = 67.2%", hjust = 0, color = "darkgrey") +
labs(x="Teacher", y="Average Grade (Percentage)") +
theme_alan() +
ggtitle("Bar Plot of Grades (By Teacher) on AS Global Perspectives EoT")
ggsave(here("EoT Grades by Teacher.png"), plot = last_plot(), device = NULL, path = NULL,
width = 8, height = 4, units = c("in", "cm", "mm"),
dpi = 600)
Most of the grades were similar here, with the notable exception being that Brindley’s class performed much better than the other classes- 16% higher than students in Alan and Devin’s class and about 9% higher than Madelyn and Suzana’s
EoTSummaryMarker <- summarySE(EoTTotals, measurevar = "Percentage", groupvars = c("Marker"))
ggplot(data=EoTSummaryMarker, aes(x=Marker, y= Percentage, fill = Marker)) +
geom_bar(stat= "summary", position = pd, width = 0.8) +
geom_errorbar(aes(ymin= Percentage - se, ymax= Percentage + se), width= 0.2, size = 1, position= pd)+
#annotate("text", x=11.5, y=7.2, label = "Average Grades", hjust = 0, fontface = "bold") +
#annotate("text", x=11.5, y=6.7, label = "Alan's Class = 52.3%", hjust = 0, color = "darkred") +
#annotate("text", x=11.5, y=6.2, label = "June's Class = 67.2%", hjust = 0, color = "darkgrey") +
labs(x="Question", y="Average Grade (Percentage)") +
theme_alan() +
ggtitle("Bar Plot of Grades (By Marker) on AS Global Perspectives EoT")
ggsave(here("EoT Grades by Marker.png"), plot = last_plot(), device = NULL, path = NULL,
width = 8, height = 4, units = c("in", "cm", "mm"),
dpi = 600)
Marking was pretty uniform, which is good. Brindley marked a bit harder and Suzana a bit easier, but this is almost certainly not significant.
EoTTotals %<>%
mutate(OwnStudent = ifelse(Teacher == Marker, "Own Student", "Other Student"))
EoTSummaryOwnStudent <- summarySE(EoTTotals, measurevar = "Percentage", groupvars = c("OwnStudent", "Marker"))
ggplot(data=EoTSummaryOwnStudent, aes(x=Marker, y= Percentage, fill = OwnStudent)) +
geom_bar(stat= "summary", position = pd, width = 0.8) +
geom_errorbar(aes(ymin= Percentage - se, ymax= Percentage + se), width= 0.2, size = 1, position= pd)+
#annotate("text", x=11.5, y=7.2, label = "Average Grades", hjust = 0, fontface = "bold") +
#annotate("text", x=11.5, y=6.7, label = "Alan's Class = 52.3%", hjust = 0, color = "darkred") +
#annotate("text", x=11.5, y=6.2, label = "June's Class = 67.2%", hjust = 0, color = "darkgrey") +
labs(x="Marker", y="Average Grade (Percentage)") +
theme_alan() +
ggtitle("Bar Plot of Grades (By Student) on AS Global Perspectives EoT")
ggsave(here("EoT Grades by Own Student.png"), plot = last_plot(), device = NULL, path = NULL,
width = 8, height = 4, units = c("in", "cm", "mm"),
dpi = 600)
Again it’s hard to say much here. Brindley and Madelyn marked their own students easier, but at least Brindley’s students were the highest students overall - so you can’t really disentangle those two things from each other.
No one other than me included grades by criteria, so we can’t really look at these.
There are many ways we could assign grade boundaries, depending on how generous we are feeling. The simplest would be to use the same grade boundaries the school usually uses: A star is 90, A is 80, B is 70, and so on and so forth. If we do that let’s take a look at where the grades would fall
AStars1 <- subset(EoTTotals, Percentage > 89.99)
AStars1$Boundary1 <- "A*"
As1 <- subset(EoTTotals, Percentage < 89.99 & Percentage > 79.99)
As1$Boundary1 <- "A"
Bs1 <- subset(EoTTotals, Percentage < 79.99 & Percentage > 69.99)
Bs1$Boundary1 <- "B"
Cs1 <- subset(EoTTotals, Percentage < 69.99 & Percentage > 59.99)
Cs1$Boundary1 <- "C"
Ds1 <- subset(EoTTotals, Percentage < 59.99 & Percentage > 49.99)
Ds1$Boundary1 <- "D"
Es1 <- subset(EoTTotals, Percentage < 49.99 & Percentage > 39.99)
Es1$Boundary1 <- "E"
Us1 <- subset(EoTTotals, Percentage < 39.99)
Us1$Boundary1 <- "U"
EoTTotals2 <- rbind.data.frame(AStars1, As1, Bs1, Cs1, Ds1, Es1, Us1)
EoTTotals2$Boundary1 <- factor(EoTTotals2$Boundary1, levels = c("U", "E", "D", "C", "B", "A", "A*"))
ggplot(data=EoTTotals2, aes(x=Boundary1)) +
geom_histogram(stat = "count", position = pd, width = 0.8) +
labs(x="Score", y="Count") +
theme_alan() +
ggtitle("AS Global Perspectives - Grade Boundaries - EoT")
ggsave(here("AS Global Perspectives- Histogram of Grade Boundaries - EoT.png"), plot = last_plot(), device = NULL, path = NULL,
width = 8, height = 6, units = c("in", "cm", "mm"),
dpi = 600)
So first thing is first we can see that the overall grades are too low if we assign grade boundaries in this way, which of course again means that we need to curve the grades, because currently the average is sitting around a C, with over 40 students at a D or below.
ggplot(data=EoTTotals2, aes(x=Boundary1, fill = Teacher)) +
geom_histogram(stat = "count", position = pd, width = 0.8) +
labs(x="Score", y="Count") +
theme_alan() +
facet_wrap( ~ Teacher, ncol = 1)+
ggtitle("AS Global Perspectives - Grade Boundaries by Teacher")
ggsave(here("AS Global Perspectives- Histogram of Grade Boundaries by Teacher.png"), plot = last_plot(), device = NULL, path = NULL,
width = 8, height = 6, units = c("in", "cm", "mm"),
dpi = 600)
We can also see the differences between the classes even more starkly here. But not much to say about them.
Lets see how well simply apply a “standard” curve to the grades by turning them into a normal distribution
library(ProfessR)
B = boxplot(EoTTotals2$Percentage, plot=FALSE)
divs = c(min(EoTTotals2$Percentage), B$stats[1:4] + diff(B$stats)/2, max(EoTTotals2$Percentage) )
D1 = do.grades(EoTTotals2$Percentage, divs=divs, tit="AS GP Presentations")
## Grade divisions:
## 7
## 36.5
## 55
## 65
## 81.5
## 93
## Letter Grade Distribution:
## 1 A+ 4
## 2 A 5
## 3 A- 1
## 4 B+ 12
## 5 B 3
## 6 B- 13
## 7 C+ 9
## 8 C 9
## 9 C- 8
## 10 D+ 14
## 11 D 13
## 12 D- 6
## 13 F 6
## [1] "Mean Score= 74.8817937378141"
So this gives us some idea of what a normal distribution around these grades would look like, but its arguably still too many students being given a D or less, and of course doesn’t include grades of U, which we also need.
count(EoTTotals2$Percentage) %>%
knitr::kable(caption = "AS GP Grade Counts", "html", row.names = F) %>%
kable_styling(full_width = F)
| x | freq |
|---|---|
| 7 | 2 |
| 13 | 1 |
| 23 | 1 |
| 27 | 1 |
| 33 | 1 |
| 37 | 2 |
| 40 | 4 |
| 43 | 4 |
| 47 | 9 |
| 50 | 5 |
| 53 | 9 |
| 57 | 8 |
| 60 | 9 |
| 63 | 9 |
| 67 | 8 |
| 70 | 5 |
| 73 | 3 |
| 77 | 7 |
| 80 | 5 |
| 83 | 1 |
| 87 | 5 |
| 90 | 3 |
| 93 | 1 |
So there you can see the counts of actual grades, which we can use to try to set boundaries as we have done before. For the EoT we have grades from 103 students.
First we set a U boundary. Let’s aim for 3 students again, which meaning all students under 20% get a U
Next are Es. Lets give 5 of those. So students between 20 and 37 get an E
Next our A-stars. We either give 4 or we give 9. As before I think better to be generous than to be stingy, so grades of 87 or higher are an A*
We gave 17 students an A on presentations. Lets only give 16 As - to the kids who scored from 73-83
We want less Ds than As, so lets give 8 of them - all the kids who scored from 40 to 43
This leaves us with 62 students between B and C. We want the numbers of these two to be about even, maybe slightly skewed towards a C (because we gave more A/Astar than the lower grades). But clumbing doesn’t always allow this, so again we have to split basically in half. So we can give 32 Bs - for students who scored from 60 - 70
This leaves us 30 grades of C, for kids with scores
We give 29 grades of B for scores between 63 and 71%, and 30 grades of C for scores between 50 and 60%
So we end up with these for grade divisions (number of scores is in brackets):
A*: >87 (9) A: 73 - 83 (16) B: 60 - 70 (32) C: 47 - 57 (30) D: 40 - 43 (8) E: 20 - 37 (5) U: <20% (3)
Now we we just need to assign the grades for these, which I do below
#A Stars - 9 students over 87%
AStars1 <- subset(EoTTotals2, Percentage > 86)
AStars1$Boundary2 <- "A*"
AStars1$PercentageCurve <- 90 + (AStars1$Percentage - 87)
#As - 16 students between 73 and 83
As1 <- subset(EoTTotals2, Percentage < 84 & Percentage > 72)
As1$Boundary2 <- "A"
As1$PercentageCurve <- (As1$Percentage - 74) + 81
#Bs - 31 students between 60 and 70
Bs1 <- subset(EoTTotals2, Percentage < 71 & Percentage > 59)
Bs1$Boundary2 <- "B"
Bs1$PercentageCurve <- round((Bs1$Percentage - 60)/1.2 + 70,2)
#Cs - 31 students between 47 and 57
Cs1 <- subset(EoTTotals2, Percentage < 58 & Percentage > 46)
Cs1$Boundary2 <- "C"
Cs1$PercentageCurve <- round((Cs1$Percentage - 46) /1.25 + 60, 0)
#Ds- 8 students between 40 and 43
Ds1 <- subset(EoTTotals2, Percentage < 44 & Percentage > 39)
Ds1$Boundary2 <- "D"
Ds1$PercentageCurve <- (Ds1$Percentage - 41) + 54
#Es- 5 students between 20 and 37
Es1 <- subset(EoTTotals2, Percentage < 38 & Percentage > 19)
Es1$Boundary2 <- "E"
Es1$PercentageCurve <- round((Es1$Percentage - 20)/2 + 40,0)
#Us - 3 Students below 20% (all set to 30% to not allow this one project to completely tank their grades)
Us1 <- subset(EoTTotals2, Percentage < 21)
Us1$Boundary2 <- "U"
Us1$PercentageCurve <- 30
EoTTotals3 <-
rbind.data.frame(AStars1, As1, Bs1, Cs1, Ds1, Es1, Us1) %>%
arrange(Student)
FinalGrades <-
EoTTotals2 %>%
arrange(Student) %>%
mutate(`Percentage (Curved)` = EoTTotals3$PercentageCurve) %>%
mutate(Boundary2 = EoTTotals3$Boundary2) %>%
subset(select = c(Student, Teacher, Grade, Percentage, `Percentage (Curved)`, Boundary2)) %>%
setNames(c("Student", "Teacher", "Grade", "Percentage", "Percentage (Curved)", "Letter Grade")) %>%
mutate(`Letter Grade` = factor(`Letter Grade`, levels = c("U", "E", "D", "C", "B", "A", "A*"))) %>%
arrange(-Percentage)
head(FinalGrades, 10)
## Student Teacher Grade Percentage Percentage (Curved) Letter Grade
## 1 Nina Wang Suzana 28 93 96 A*
## 2 Kyle Cheng Suzana 27 90 93 A*
## 3 Makayla Chen Brindley 27 90 93 A*
## 4 Tony Wu Brindley 27 90 93 A*
## 5 Amy An Suzana 26 87 90 A*
## 6 Chelsea Wang Suzana 26 87 90 A*
## 7 Erica Zhao Suzana 26 87 90 A*
## 8 Frank Wu Alan 26 87 90 A*
## 9 Paulin Zhang Madelyn 26 87 90 A*
## 10 Rika Chen Madelyn 25 83 90 A
So now lets look at the distribution of the grades now
ggplot(data=FinalGrades, aes(x=`Percentage (Curved)` , fill = `Letter Grade`)) +
geom_histogram(stat = "count", position = pd, width = 0.8) +
labs(x="Score", y="Count") +
theme_alan() +
ggtitle("AS Global Perspectives - Revised Distribution of Letter Grades")
Woohoo - looks pretty good. Lets output this as some spreadsheets
write.csv(FinalGrades, here("AS GP Revised EoT.csv"))
#Alan
write.csv(subset(FinalGrades, Teacher == "Alan"), here("AS GP Revised EoT- Alan.csv"))
#Brindley
write.csv(subset(FinalGrades, Teacher == "Brindley"), here("AS GP Revised EoT- Brindley.csv"))
#Devin
write.csv(subset(FinalGrades, Teacher == "Devin"), here("AS GP Revised EoT- Devin.csv"))
#Madelyn
write.csv(subset(FinalGrades, Teacher == "Madelyn"), here("AS GP Revised EoT- Madelyn.csv"))
#Suzana
write.csv(subset(FinalGrades, Teacher == "Suzana"), here("AS GP Revised EoT- Suzana.csv"))
If you have any questions or comments about student performance in the class, please don’t hesitate to get in touch via email to Alan Nielsen.
This report was generated using R Markdown.