Loading Libraries and Setup

Please do not tinker with this code chunk. I leave it here in case you’re curious how any of this works.

theme_alan <- function(base_size = 12 , base_family = "")
{
  half_line <- base_size/2
  colors <- ggthemes_data$few
  gray <- colors$medium["gray"]
  black <- colors$dark["black"]
  
  theme(
    line = element_line(colour = "black", size = 0.5, linetype = 1, lineend = "butt"),
    rect = element_rect(fill = "white", 
                        colour = "black", size = 0.5, linetype = 1),
    text = element_text(family = base_family, face = "plain", colour = "black", 
                        size = base_size, lineheight = 0.9, hjust = 0.5, vjust = 0.5,
                        angle = 0, margin = margin(), debug = FALSE),
    
    axis.line = element_blank(),
    axis.line.x = NULL,
    axis.line.y = NULL, 
    axis.text = element_text(size = rel(0.8), colour = "grey30"),
    axis.text.x = element_text(margin = margin(t = 0.8 * half_line/2), vjust = 1),
    axis.text.x.top = element_text(margin = margin(b = 0.8 * half_line/2), vjust = 0),
    axis.text.y = element_text(margin = margin(r = 0.8 * half_line/2), hjust = 1),
    axis.text.y.right = element_text(margin = margin(l = 0.8 * half_line/2), hjust = 0), 
    axis.ticks = element_line(colour = "grey20"), 
    axis.ticks.length = unit(half_line/2, "pt"),
    axis.title.x = element_text(margin = margin(t = half_line), vjust = 1),
    axis.title.x.top = element_text(margin = margin(b = half_line), vjust = 0),
    axis.title.y = element_text(angle = 90, margin = margin(r = half_line), vjust = 1),
    axis.title.y.right = element_text(angle = -90, margin = margin(l = half_line), vjust = 0),
    
    legend.background = element_rect(colour = NA),
    legend.spacing = unit(0.4, "cm"), 
    legend.spacing.x = NULL, 
    legend.spacing.y = NULL,
    legend.margin = margin(0.2, 0.2, 0.2, 0.2, "cm"),
    legend.key = element_rect(fill = "white", colour = NA), 
    legend.key.size = unit(1.2, "lines"), 
    legend.key.height = NULL,
    legend.key.width = NULL,
    legend.text = element_text(size = rel(0.8)), 
    legend.text.align = NULL,
    legend.title = element_text(hjust = 0),
    legend.title.align = NULL,
    legend.position = "right", 
    legend.direction = NULL,
    legend.justification = "center", 
    legend.box = NULL,
    legend.box.margin = margin(0, 0, 0, 0, "cm"),
    legend.box.background = element_blank(),
    legend.box.spacing = unit(0.4, "cm"),
    
    panel.background = element_rect(fill = "white", colour = NA),
    panel.border = element_rect(fill = NA, colour = "grey20"),
    panel.grid.major = element_line(colour = "grey92"),
    panel.grid.minor = element_line(colour = "grey92", size = 0.25),
    panel.spacing = unit(half_line, "pt"),
    panel.spacing.x = NULL,
    panel.spacing.y = NULL,
    panel.ontop = FALSE,
    
    strip.background = element_rect(fill = "NA", colour = "NA"),
    strip.text = element_text(colour = "grey10", size = rel(0.8)),
    strip.text.x = element_text(margin = margin(t = half_line, b = half_line)),
    strip.text.y = element_text(angle = 0, margin = margin(l = half_line, r = half_line)),
    strip.placement = "inside",
    strip.placement.x = NULL, 
    strip.placement.y = NULL,
    strip.switch.pad.grid = unit(0.1, "cm"), 
    strip.switch.pad.wrap = unit(0.1, "cm"), 
    
    plot.background = element_rect(colour = "white"),
    plot.title = element_text(size = rel(1.2), hjust = 0, vjust = 1, margin = margin(b = half_line * 1.2)),
    plot.subtitle = element_text(size = rel(0.9), hjust = 0, vjust = 1, margin = margin(b = half_line * 0.9)),
    plot.caption = element_text(size = rel(0.9), hjust = 1, vjust = 1, margin = margin(t = half_line * 0.9)), 
    plot.margin = margin(half_line, half_line, half_line, half_line),
    
    complete = TRUE)
}

# Wrapper Function for Long Graph Titles
wrapper <- function(x, ...) 
{
  paste(strwrap(x, ...), collapse = "\n")
}

#RDFZ Reds
RDFZReds <- c("#cf8f8d", "#ae002b", "#991815", "#78011e", "#4b0315")

#Grade Colors
GradeColors <- c("#8900df", "#0092df", "#00df76", "#94df00", "#BA9900", "#DF7800", "#C85500", "#B23200", "#9b0f00")

#Grade Fill Scale
scale_fill_lettergrades <- function(...){
  ggplot2:::manual_scale(
    "fill",
    values = setNames(GradeColors, c("A*", "A", "B", "C", "D", "E", "F", "G", "U")),
    ...
  )
}

#function for allowing inline code chunks to be shown verbatim
rinline <- function(code){
  html <- '<code  class="r">``` `r CODE` ```</code>'
  sub("CODE", code, html)
}

#function for removing empty columns
col_selector <- function(x) {
  return(!(all(is.na(x)) | all(x == "")))
}

library(tidyverse)  # basic data handling and plotting
library(ggthemes)   # used to give additional styling options for graphs
library(plyr)       # some data handling commands not included in tidyverse that I find useful
library(kableExtra) # used for creating beautiful and interactive table objects
library(magrittr)   # used for additional "pipes" for writing more complex code
library(here)       # used for simple file indexing
library(ggrepel)    # a graphing utility for scatterplots
library(tippy)      # used for embedding tooltips in R Markdown
library(janitor)    # for some extra data handling commands
library(ggpubr)     # for making grid arrangements of tables with figures
library(gridExtra)  # for turning tables into grobs for the above
library(formattable)
## Setting up for Letter Grades

#IG
Letters <- c("A*", "A", "B", "C", "D", "E", "F", "G", "U")
MinVal <- c(89.5, 79.5, 69.5, 59.5, 49.5, 39.5, 29.5, 19.5, 0)
MaxVal <- c (100, 89.49, 79.49, 69.49, 59.49, 49.49, 39.49, 29.49, 19.49)

IGLetterBoundaries <- 
  cbind.data.frame(Letters, MinVal, MaxVal) %>%
    setNames(c("Letter", "Bottom", "Top")) %>%
    mutate(Letter = factor(Letter, levels = c("A*", "A", "B", "C", "D", "E", "F", "G", "U")))

ASLetterBoundaries <- rbind.data.frame(IGLetterBoundaries[2:6,], IGLetterBoundaries[9,])

A2LetterBoundaries <- rbind.data.frame(IGLetterBoundaries[1:6,], IGLetterBoundaries[9,])
 
rm(Letters, MinVal, MaxVal)

Basic Data Analysis

Now we can load in the Component Scores (which contains all the other scores as well) and combine these two into a single more useful and readable dataframe

# Read in the Mock Exam Data with UTF-8 Encoding and Rename
EngMock2021 <- 
  read.csv(here("./Data/Input/EngMock2021.csv"), encoding = "UTF-8") %>%
    setNames(c("Chinese", "First", "Last", "Level", "Subject", "MockResult", "Year", "Teacher")) %>%
    mutate(FullName = paste(First, Last, sep = " ")) %>%
    distinct() %>%
    mutate(Combo = paste(Level, Subject, FullName, sep = "-")) 
  
## Read in the Data File with UTF-8 Encoding
EngComponents2021 <- read.csv(here("./Data/Input/EngComponents2021.csv"), encoding = "UTF-8")

## Clean up the column names
EngComponents2021 %<>%
  setNames(c("Subject", "Level", "Course", "CandNum", "Last", "CFirst", "First",
             "Comp01Raw", "Comp01Adj", "Comp01Letter",
             "Comp02Raw", "Comp02Adj", "Comp02Letter",
             "Comp03Raw", "Comp03Adj", "Comp03Letter",
             "Comp04Raw", "Comp04Adj", "Comp04Letter",
             "Comp12Raw", "Comp12Adj", "Comp12Letter", 
             "Comp13Raw", "Comp13Adj", "Comp13Letter",
             "Comp22Raw", "Comp22Adj","Comp22Letter", 
             "Comp32Raw", "Comp32Adj", "Comp32Letter", 
             "Comp42Raw", "Comp42Adj", "Comp42Letter", 
             "Comp52Raw", "Comp52Adj", "Comp52Letter",
             "SyllTotal", "SyllLetter", "SyllPerc" 
             )) %>%
  mutate(SyllLetter = toupper(SyllLetter)) %>%
  mutate(SyllLetter = factor(SyllLetter, levels = unique(IGLetterBoundaries$Letter))) %>%
  mutate(Course = factor(Course, levels = c(
      "IG Art", "AS Art", "A2 Art",
      "IG Drama",
      "IG ESOL",
      "IG Global Perspectives", "AS Global Perspectives", "A2 Global Perspectives",
      "A2 Literature",
      "IG Music", "AS Music", "A2 Music")
      ))%>%
    mutate(Subject = factor(Subject, levels = c("Art", "Drama", "ESOL", "Global Perspectives", "Literature", "Music"))) %>%
    mutate(Level = factor(Level, levels = c("IG", "AS", "A2"))) %>%
    mutate(FullName = paste(First, Last, sep = " ")) %>%
    mutate(Combo = paste(Level, Subject, FullName, sep = "-")) %>%
    mutate(Teacher = plyr::mapvalues(Combo, from = EngMock2021$Combo, to = EngMock2021$Teacher))


## Read in Last Year's Data File with UTF-8 Encoding
Results2020 <- 
  read.csv(here("./Data/Input/Results2020.csv"), encoding = "UTF-8") %>%
    setNames(c("Grade", "Chinese", "FullName", "CandNum","Letter", "Level", "Subject", "Course"))  %>% 
    mutate(Letter = toupper(Letter)) %>%
    mutate(Letter = factor(Letter, levels = unique(IGLetterBoundaries$Letter))) %>%
    mutate(Year = "2020") %>%
    mutate(finder = paste(CandNum, Course))  %>%
    mutate(Combo = paste(Level, Subject, FullName, sep = "-"))

  # Assign Teachers
### Can't figure out how to write this as a for loop. Brute force here... (may be some way to do with with case_when)

Plotting Overall Data

Analysis by Level (IG/AS/A2)

The simplest thing we can do with the data that we now have in this nice format is to take some basic looks at the distributions of grades at the three levels.

Levels <- unique(EngComponents2021$Level)

for (level in Levels){
  
  if (level == "IG"){FocalLetters <- IGLetterBoundaries$Letter}
  if (level == "AS"){FocalLetters <- ASLetterBoundaries$Letter}
  if (level == "A2"){FocalLetters <- A2LetterBoundaries$Letter}

  FocalData <- 
    EngComponents2021 %>%
      subset(Level == level) %>%
      mutate(SyllLetter = toupper(SyllLetter)) %>%
      mutate(SyllLetter = factor(SyllLetter, levels = FocalLetters)) %>%
      mutate(SyllTotal = as.numeric(as.character(SyllTotal))) %>%
      drop_na(SyllLetter) %>%
      mutate(SyllPerc = as.numeric((SyllPerc)))

  BaseTitle <- "2021 Overall Results"
  FocalTitle <- paste(BaseTitle, " - ", level, sep = "")
  FigurePath <- paste(here(), "/Figures/Overall/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Overall/2021/", sep = "")
  dir.create(FigurePath)
  DataPath <- paste(here(), "/Data/Overall/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Overall/2021/", sep = "")
  dir.create(DataPath)

  #Counts Plot
  FocalPlot <-
    ggplot(data= FocalData , aes(x=SyllLetter, fill = SyllLetter)) +
    geom_bar(stat = "count", width = 0.8) +
    scale_x_discrete(breaks = FocalLetters, limits = rev, drop = FALSE) +
    scale_y_continuous(breaks = c(0, 5, 10, 15, 20, 25, 30, 35, 40)) +
    scale_fill_lettergrades() +  
    labs(x="Letter Grade", y="Count") +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper(FocalTitle, width = 60))

   ggsave(paste(FigurePath, FocalTitle, " - Counts",  ".png", sep = ""), 
    plot = FocalPlot, device = NULL, path = NULL,
    width = 8, height = 3, units = c("in"),
    dpi = 300)
  
   #Percentage Plot
  StackedFacet <-
    ggplot(data= FocalData , aes(x=Level, fill = SyllLetter)) +
    geom_bar(position = "fill") +
    scale_fill_lettergrades() +  
    labs(x="", y="Cumulative Percentage") +
    coord_flip() +
    theme_alan() +
    theme(legend.position = "bottom") +
    guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade")) +
    ggtitle(wrapper("", width = 60))

  ggsave(paste(FigurePath, FocalTitle, " - Percentage", ".png", sep = ""),
       plot = StackedFacet, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300)

#Tables
  TTitle <- paste(BaseTitle, " III - ", level,  sep = "")  

  FocalCounts <- 
    data.frame(table(FocalData$SyllLetter)) %>%  
    setNames(c("Letter Grade", "Count")) %>%
    mutate(Percentage = Count/nrow(FocalData)*100) %>%
    mutate(Cumulative = cumsum(Percentage)) %>%
    mutate_if(is.double, round, 1)
  
    write.csv(FocalCounts, paste(DataPath, TTitle, ".csv", sep = ""))
    
   FocalCountsKable <-
     FocalCounts %>%    
      knitr::kable(caption = TTitle, row.names = F) %>%
      row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
      kable_styling(full_width = FALSE, 
                  bootstrap_options = c("striped", "hover", "condensed"),
                  fixed_thead = TRUE)
  
    save_kable(FocalCountsKable, paste(FigurePath, TTitle, " - Table", ".png", sep = ""))
    
    
    
  FocalCountsKableGrob <- tableGrob(FocalCounts, theme = ttheme_minimal())

  # Combined Plot
  CombinedPlot <- 
    ggpubr::ggarrange(FocalPlot, StackedFacet, FocalCountsKableGrob, nrow = 3) 
  
  ComboTitle <- paste(BaseTitle, " - Combination - ", level, sep = "")
  
    ggsave(paste(FigurePath, ComboTitle, ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 8, height = 8, units = c("in"),
       dpi = 300)

}

filestoshow <- 
    rev(paste("![](", list.files(FigurePath, pattern = "*Combination", full.names = TRUE), ")", sep = ""))


rm(level, Levels, FocalTitle, FocalScale, FocalLevel, FocalLetters, 
   FocalCounts, FocalData, FocalPlot, FocalBoundaries, FocalCountsKable,
   CPTitle, DataPath, FigurePath, file, fileshower, PPTitle, TTitle, BaseTitle)

Analysis by Course

This is good to know, but probably more valuable to break this apart on a by-course basis, which we do below.

BaseTitle <- "2021 Results by Course"
FigurePath <- paste(here(), "/Figures/Course/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Course/2021/", sep = "")
  dir.create(FigurePath)
  DataPath <- paste(here(), "/Data/Course/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Course/2021/", sep = "")
  dir.create(DataPath)

# Counts Plot
CountPlot  <-
  ggplot(data= EngComponents2021, aes(x=SyllLetter, fill = SyllLetter)) +
    geom_bar(stat = "count", width = 0.8) +
    scale_x_discrete(breaks = levels(EngComponents2021$SyllLetter), limits = rev, drop = FALSE) +
    scale_y_continuous(breaks = c(0, 10, 20, 30, 40)) +
    scale_fill_lettergrades() +   
    labs(x="Letter Grade", y="Count") +
    facet_grid(Level ~ Subject, scales = "free") +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper(BaseTitle, width = 60))
  

ggsave(paste(FigurePath, BaseTitle, " - Counts", ".png", sep = ""),
       plot = CountPlot , device = NULL, path = NULL,
       width = 10, height = 3, units = c("in"),
       dpi = 600)


#Percentage Plot

PercPlot  <-
  ggplot(data= EngComponents2021 , aes(x=Level, fill = SyllLetter)) +
  geom_bar(position = "fill") +
  scale_fill_lettergrades() +  
  labs(x="", y="Cumulative Percentage") +
  facet_grid(Level ~ Subject, scales = "free") +
  coord_flip() +
  theme_alan() +
  theme(legend.position = "bottom") +
  guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade")) 

ggsave(paste(FigurePath, BaseTitle, " - Percentage", ".png", sep = ""),
       plot = PercPlot , device = NULL, path = NULL,
       width = 10, height = 3, units = c("in"),
       dpi = 300)


  # Combined Plot
  CombinedPlot <- 
    ggpubr::ggarrange(CountPlot, PercPlot, nrow = 2) 
  
  ComboTitle <- paste(BaseTitle, " - Combination - ", sep = "")
  
    ggsave(paste(FigurePath, ComboTitle, ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 10, height = 5, units = c("in"),
       dpi = 300)

filestoshow <- 
    rev(paste("![](", list.files(FigurePath, pattern = "*Combination", full.names = TRUE), ")", sep = ""))

Results by Course - Summary

We can also take a look at these as a Table instead of just as graphs.

Levels <- unique(EngComponents2021$Level)

for (level in Levels){
  
  Title <- paste(level, " Results - By Course", sep = "")

  if (level == "IG"){FocalLetters <- IGLetterBoundaries$Letter}
  if (level == "AS"){FocalLetters <- ASLetterBoundaries$Letter}
  if (level == "A2"){FocalLetters <- A2LetterBoundaries$Letter}
  
  FocalData <- 
    EngComponents2021 %>%
      subset(Level == level) %>%
      mutate(SyllLetter = factor(SyllLetter, levels = FocalLetters))
  
  subjects <- levels(FocalData$Subject)
  subjectT <- paste(subjects, "Total")
  subjectP <- paste(subjects, "Percentage")
  subjectCum <- paste(subjects, "CumSum")
  
  subjecttotals <- table(FocalData$Subject)
  
  FocalLetterCounts <- 
    FocalLetters %>%
      data.frame() %>%
        mutate(C1 = data.frame(table(subset(FocalData, Subject == subjects[1])$SyllLetter))$Freq) %>%
        mutate(C2 = data.frame(table(subset(FocalData, Subject == subjects[2])$SyllLetter))$Freq) %>%
        mutate(C3 = data.frame(table(subset(FocalData, Subject == subjects[3])$SyllLetter))$Freq) %>%
        mutate(C4 = data.frame(table(subset(FocalData, Subject == subjects[4])$SyllLetter))$Freq) %>%
        mutate(C5 = data.frame(table(subset(FocalData, Subject == subjects[5])$SyllLetter))$Freq) %>%
        mutate(C6 = data.frame(table(subset(FocalData, Subject == subjects[6])$SyllLetter))$Freq) %>%
        mutate(C1Total = subjecttotals[1]) %>%
        mutate(C2Total = subjecttotals[2]) %>%
        mutate(C3Total = subjecttotals[3]) %>%
        mutate(C4Total = subjecttotals[4]) %>%
        mutate(C5Total = subjecttotals[5]) %>%
        mutate(C6Total = subjecttotals[6]) %>%    
        mutate(C1Perc = C1/C1Total*100) %>%
        mutate(C2Perc = C2/C2Total*100) %>%    
        mutate(C3Perc = C3/C3Total*100) %>%   
        mutate(C4Perc = C4/C4Total*100) %>%
        mutate(C5Perc = C5/C5Total*100) %>%
        mutate(C6Perc = C6/C6Total*100) %>%
        mutate(C1PercCum = cumsum(C1Perc)) %>%
        mutate(C2PercCum = cumsum(C2Perc)) %>%
        mutate(C3PercCum = cumsum(C3Perc)) %>%    
        mutate(C4PercCum = cumsum(C4Perc)) %>%  
        mutate(C5PercCum = cumsum(C5Perc)) %>%  
        mutate(C6PercCum = cumsum(C6Perc)) %>%  
        mutate_if(is.double, round, 1) %>%
        setNames(c("Letter Grade", subjects, subjectT, subjectP, subjectCum)) %>%
        dplyr::select(c(
          "Letter Grade",
          subjects[1], subjectP[1], subjectCum[1],
          subjects[2], subjectP[2], subjectCum[2],
          subjects[3], subjectP[3], subjectCum[3],
          subjects[4], subjectP[4], subjectCum[4],
          subjects[5], subjectP[5], subjectCum[5],
          subjects[6], subjectP[6], subjectCum[6]
                  ))

    write.csv(FocalLetterCounts, paste(DataPath, Title, ".csv", sep = ""))
  
  FocalLetterCountsKable <-
    FocalLetterCounts %>%
      setNames(c("Letter Grade", rep(list("Count", "%", "Cum %"), length(subjects)))) %>%
        knitr::kable(caption = Title, row.names = F, align = "lcccccccccccc") %>%
          row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
            column_spec(1, width = "1.5cm") %>%
            column_spec(seq(from = 1, to = (1 + (length(subjects)-1)*3), by= 3), border_right = T) %>%
              ### Can't Figure out how to add headers anything other than manually!
            add_header_above(c(" " = 1, "Art and Design" = 3, "Drama" = 3, "ESOL" = 3,
                               "Global Perspectives" = 3, "Literature" = 3, "Music" = 3)) %>%
            kable_styling(full_width = FALSE, 
              bootstrap_options = c("striped", "hover", "condensed"),
              fixed_thead = TRUE, 
              position = "center")

  save_kable(FocalLetterCountsKable, paste(FigurePath, Title, " - Table", ".png", sep = ""))

}

Results by Course

We might also want these as separate graphs and tables for individual courses, for our own records and/or for tidiness, so lets output those.

Courses <- levels(EngComponents2021$Course)

for (course in Courses){
  
  FocalLevel <- as.data.frame(str_split(course, " "))[1,]
  FocalSubject <- as.data.frame(str_split(course, " "))[2,]
  
  if (FocalLevel == "IG"){FocalLetters <- factor(IGLetterBoundaries$Letter, levels = c("A*", "A", "B", "C", "D", "E", "F", "G", "U"))}
  if (FocalLevel == "AS"){FocalLetters <- factor(ASLetterBoundaries$Letter, levels = c("A", "B", "C", "D", "E", "U"))}
  if (FocalLevel == "A2"){FocalLetters <- factor(A2LetterBoundaries$Letter, levels = c("A*", "A", "B", "C", "D", "E", "U"))}

  FocalData <- 
    EngComponents2021 %>%
      subset(Course == course) %>%
      mutate(SyllLetter = factor(SyllLetter, levels = FocalLetters)) 
  
  BaseTitle <- "2021 Results"
  FocalTitle <- paste(BaseTitle, " - ", course, sep = "")
  FigurePath <- paste(here(), "/Figures/Course/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Course/2021/", sep = "")
  dir.create(FigurePath)  
  FigurePathCourse <- paste(FigurePath, FocalSubject, "/", sep = "")
  dir.create(FigurePathCourse) 
  DataPath <- paste(here(), "/Data/Course/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Course/2021/", sep = "")
  dir.create(DataPath)

# Count Plot
  CountPlot <-
    ggplot(data= FocalData , aes(x=SyllLetter, fill = SyllLetter)) +
      geom_bar(stat = "count", width = 0.8) +
      scale_x_discrete(breaks = levels(IGLetterBoundaries$Letter), limits = rev, drop = FALSE) +
      scale_y_continuous(breaks = c(0, 5, 10, 15, 20, 25, 30)) +
      scale_fill_lettergrades() +  
      labs(x="Letter Grade", y="Count") +
      theme_alan() +    
      theme(legend.position = "none") +
      ggtitle(wrapper(FocalTitle, width = 60))

  ggsave(paste(FigurePathCourse, FocalTitle, " - Counts", ".png", sep = ""), 
       plot = CountPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300)
  
# Percentage Plot
PercPlot <-
  ggplot(data= FocalData , aes(x= Level, fill = SyllLetter)) +
  geom_bar(position = "fill") +
  scale_fill_lettergrades() +  
  labs(x="", y="Cumulative Percentage") +
  coord_flip() +
  theme_alan() +
  theme(legend.position = "bottom") +
  guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade")) 

ggsave(paste(FigurePathCourse, FocalTitle, " - Percentage", ".png", sep = ""),
       plot = PercPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300)
 
# Counts Tables 
   FocalCounts <- 
    data.frame(table(FocalData$SyllLetter)) %>%  
    setNames(c("Letter Grade", "Count")) %>%
    mutate(Percentage = Count/nrow(FocalData)*100) %>%
    mutate(Cumulative = cumsum(Percentage)) %>%
    mutate_if(is.double, round, 1) 
  
  write.csv(FocalCounts, paste(DataPath, FocalTitle, ".csv", sep = ""))
  
  FocalCountsKable <-
    FocalCounts %>%
    knitr::kable(caption = FocalTitle, row.names = F) %>%
    row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
    kable_styling(full_width = FALSE, 
                  bootstrap_options = c("striped", "hover", "condensed"),
                  fixed_thead = TRUE)
  
  save_kable(FocalCountsKable, paste(FigurePathCourse, FocalTitle, " - Table", ".png", sep = ""))
  


  # Combined Plot
  
  FocalCountsKableGrob <- tableGrob(FocalCounts, theme = ttheme_minimal())
    
  CombinedPlot <- 
    ggpubr::ggarrange(CountPlot, PercPlot, FocalCountsKableGrob, nrow = 3) 
  
  ComboTitle <- paste(BaseTitle, " - Combination - ", course, sep = "")
  
    ggsave(paste(FigurePath, ComboTitle, ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 8, height = 8, units = c("in"),
       dpi = 300)
  
}

filestoshow <- 
    rev(paste("![](", list.files(FigurePath, pattern = "*Combination", full.names = TRUE), ")", sep = ""))

Art and Design

Drama

ESOL

Global Perspectives

Literature

Music

Analysis by Teacher

  BaseTitle <- "2021 Overall Results - Courses by Teacher"
  FigurePath <- paste(here(), "/Figures/Teacher/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Teacher/2021/", sep = "")
  dir.create(FigurePath)
  DataPath <- paste(here(), "/Data/Teacher/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/2021/", sep = "")
  dir.create(DataPath)
  
  PercPlot  <-
    ggplot(data= EngComponents2021 , aes(x=Level, fill = SyllLetter)) +
    geom_bar(position = "fill") +
    scale_fill_lettergrades() +  
    scale_x_discrete(drop = FALSE) +
    labs(x="", y="Cumulative Percentage") +
    facet_grid(Teacher ~ Subject, scales = "free_y", drop = TRUE) +
    coord_flip() +
    theme_alan() +
    ggtitle(wrapper(BaseTitle, width = 60))

ggsave(here(paste(FigurePath, BaseTitle, ".png", sep = "")),
       plot = PercPlot, device = NULL, path = NULL,
       width = 10, height = 4.5, units = c("in"),
       dpi = 300)

EngComponents2021 %<>%
  unite(Combo, Course, Teacher, sep = " ", remove = FALSE) %>%
  mutate(Combo = factor(Combo, levels = c(
    "IG ESOL Erin Ju",
    "IG ESOL Jasmine Jin" ,
    "IG ESOL Sabrina jia",
    "IG ESOL Devin Howard",
    "IG ESOL Abby Zhang",
    "A2 Literature Jay James May",
    "IG Global Perspectives Jeffrey Thornton",
    "IG Global Perspectives Jay James May",
    "AS Global Perspectives Madelyn Wang",
    "AS Global Perspectives Mosala Sehloho",
    "AS Global Perspectives Jeffrey Thornton",
    "AS Global Perspectives Alan Nielsen",
    "A2 Global Perspectives Devin Howard",
    "IG Art Milos Colic",
    "AS Art Milos Colic" ,
    "A2 Art Milos Colic",
    "IG Music Mavis",
    "AS Music Mavis",
    "A2 Music Mavis",
    "IG Drama Sabrina"
    
      )
    )
  )


Combos <- levels(EngComponents2021$Combo)

for (combo in Combos){
  
  FocalLevel <- as.data.frame(str_split(combo, " "))[1,]
  
  if (FocalLevel == "IG"){FocalLetters <- factor(IGLetterBoundaries$Letter, levels = c("A*", "A", "B", "C", "D", "E", "F", "G", "U"))}
  if (FocalLevel == "AS"){FocalLetters <- factor(ASLetterBoundaries$Letter, levels = c("A", "B", "C", "D", "E", "U"))}
  if (FocalLevel == "A2"){FocalLetters <- factor(A2LetterBoundaries$Letter, levels = c("A*", "A", "B", "C", "D", "E", "U"))}

  FocalSubject <- as.data.frame(str_split(combo, " "))[2,]
  FocalTeacher <- as.data.frame(str_split(combo, " "))[3,]
  FocalCourse <- paste(FocalLevel, FocalSubject, sep = " ")

  FocalData <- 
    EngComponents2021 %>%
      subset(Combo == combo) %>%
      mutate(SyllLetter = factor(SyllLetter, levels = FocalLetters)) 

  BaseTitle <- "2021 Results"
  FocalTitle <- paste(BaseTitle, " - ", FocalCourse, " - ", FocalTeacher, sep = "")
  FigurePath <- paste(here(), "/Figures/Teacher/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Teacher/2021/", sep = "")
  dir.create(FigurePath)
  FigurePathInd <- paste(FigurePath, FocalTeacher, "/", sep = "")
  dir.create(FigurePathInd) 
  
  DataPath <- paste(here(), "/Data/Teacher/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/2021/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/2021/", FocalTeacher, "/", sep = "")
  dir.create(DataPath) 

# Count Plot 
  CountPlot<-  
    ggplot(data= FocalData , aes(x=SyllLetter, fill = SyllLetter)) +
      geom_bar(stat = "count", width = 0.8) +
      scale_x_discrete(breaks = FocalLetters, limits = rev, drop = FALSE) +
      scale_y_continuous(breaks = c(0, 5, 10, 15, 20, 25, 30)) +
      scale_fill_lettergrades() +  
      labs(x="Letter Grade", y="Count") +
      theme_alan() +
      theme(legend.position = "none") +
      ggtitle(wrapper(FocalTitle, width = 60))
  
  ggsave(paste(FigurePathInd, FocalTitle, " - Counts",  ".png", sep = ""), 
    plot = CountPlot, device = NULL, path = NULL,
    width = 8, height = 3, units = c("in"),
    dpi = 300)
  
  # Percentage Plot 
  
  PercPlot<- 
    ggplot(data= FocalData , aes(x= Level, fill = SyllLetter)) +
    geom_bar(position = "fill") +
    scale_fill_lettergrades() +  
    labs(x="", y="Cumulative Percentage") +
    coord_flip() +
    theme_alan() +
    theme(legend.position = "bottom") +
    guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade")) 

  ggsave(paste(FigurePathInd, FocalTitle, " - Percentage", ".png", sep = ""),
       plot = PercPlot, device = NULL, path = NULL,
       width = 6, height = 2.5, units = c("in"),
       dpi = 300)
  
  
  #Table
  FocalCounts <- 
    data.frame(table(FocalData$SyllLetter)) %>%  
    setNames(c("Letter Grade", "Count")) %>%
    mutate(Percentage = Count/nrow(FocalData)*100) %>%
    mutate(Cumulative = cumsum(Percentage)) %>%
    mutate_if(is.double, round, 1) 
  
  write.csv(FocalCounts, paste(DataPath, FocalTitle, ".csv", sep = ""))
  
  FocalCountsKable <-
    FocalCounts %>%
    knitr::kable(caption = FocalTitle, row.names = F) %>%
    row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
    kable_styling(full_width = FALSE, 
                  bootstrap_options = c("striped", "hover", "condensed"),
                  fixed_thead = TRUE)
  
  save_kable(FocalCountsKable, paste(FigurePathInd, FocalTitle, " - Table", ".png", sep = ""))

  # Combined Plot
  
  FocalCountsKableGrob <- tableGrob(FocalCounts, theme = ttheme_minimal())
    
  CombinedPlot <- 
    ggpubr::ggarrange(CountPlot, PercPlot, FocalCountsKableGrob, nrow = 3) 
  
  ggsave(paste(FigurePath, FocalTitle, " - Combination", ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 8, height = 8, units = c("in"),
       dpi = 300)

}

rm(level, Levels, FocalTitle, FocalScale, FocalLevel, FocalLetters, 
   FocalCounts, FocalData, FocalPlot, FocalBoundaries)

These can be found on OneDrive

Comparing to Last Year’s Results

One of the things that each of us is required to do is to compare this years results to last - so lets do that. Thank Raj for getting me a copy of last year’s results. The file I was sent for last year contains everything, and spread across multiple sheets, so I had to clean it up fairly extensively in excel before saving it as a usable CSV for using in R. (NB- I could have done this cleaning up in R but this is one case where it would have been fiddly to do so - this is actually WHY I use R for my whole data ecosystem - so that I don’t have to go through things and clean them up and standardize!)

## Subset out SS Data and Complete formatting
EngResults2020 <-
  Results2020 %>%
    subset(Subject == "Art and Design"|Subject == "Drama"|Subject == "ESOL"
           |Subject == "Global Perspectives"|Subject == "Literature"|Subject == "Music") %>%
    mutate(Course = factor(Course, levels = c(
      "IG Art and Design", "AS Art and Design", "A2 Art and Design",
      "IG Drama", "AS Drama", "A2 Drama",
      "IG ESOL",
      "IG Global Perspectives", "AS Global Perspectives", "A2 Global Perspectives",
      "IG Literature", "AS Literature", "A2 Literature",
      "IG Music", "AS Music", "A2 Music")
      ))%>%
    mutate(Level = factor(Level, levels = c("IG", "AS", "A2"))) %>%
    mutate(Teacher = "Unknown") %>%
    dplyr::select(-c(finder, Grade))

Lets take a look at last year’s grade distributions to remind us what they looked like

Visualising 2020 Results

Levels <- unique(EngResults2020$Level)

for (level in Levels){
  
  if (level == "IG"){FocalLetters <- IGLetterBoundaries$Letter}
  if (level == "AS"){FocalLetters <- ASLetterBoundaries$Letter}
  if (level == "A2"){FocalLetters <- A2LetterBoundaries$Letter}

  FocalData <- 
    EngResults2020 %>%
      subset(Level == level) %>%
      drop_na(Letter) 

  BaseTitle <- "2020 Overall Results"
  FocalTitle <- paste(BaseTitle, " - ", level, sep = "")
  FigurePath <- paste(here(), "/Figures/Overall/2020/", sep = "")
  dir.create(FigurePath)
  DataPath <- paste(here(), "/Data/Overall/2020/", sep = "")
  dir.create(DataPath)

  #Counts Plot
  CountPlot <-
    ggplot(data= FocalData , aes(x=Letter, fill = Letter)) +
    geom_bar(stat = "count", width = 0.8) +
    scale_x_discrete(breaks = FocalLetters, limits = rev, drop = FALSE) +
    scale_y_continuous(breaks = c(0, 5, 10, 15, 20, 25, 30, 35, 40)) +
    scale_fill_lettergrades() +  
    labs(x="Letter Grade", y="Count") +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper(FocalTitle, width = 60))

   ggsave(paste(FigurePath, FocalTitle, " - Counts",  ".png", sep = ""), 
    plot = CountPlot, device = NULL, path = NULL,
    width = 8, height = 3, units = c("in"),
    dpi = 300)
  
   #Percentage Plot
  PercPlot <-
  ggplot(data= FocalData , aes(x=Level, fill = Letter)) +
  geom_bar(position = "fill") +
  scale_fill_lettergrades() +  
  labs(x="", y="Cumulative Percentage") +
  coord_flip() +
  theme_alan() +
  theme(legend.position = "bottom") +
  guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade")) 

  ggsave(paste(FigurePath, FocalTitle, " - Percentage", ".png", sep = ""),
       plot = PercPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300)

#Tables
  FocalCounts <- 
    data.frame(table(FocalData$Letter)) %>%  
    setNames(c("Letter Grade", "Count")) %>%
    mutate(Percentage = Count/nrow(FocalData)*100) %>%
    mutate(Cumulative = cumsum(Percentage)) %>%
    mutate_if(is.double, round, 1)
  
    write.csv(FocalCounts, paste(DataPath, FocalTitle, ".csv", sep = ""))
    
   FocalCountsKable <-
     FocalCounts %>%    
      knitr::kable(caption = FocalTitle, row.names = F) %>%
      row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
      kable_styling(full_width = FALSE, 
                  bootstrap_options = c("striped", "hover", "condensed"),
                  fixed_thead = TRUE)
  
    save_kable(FocalCountsKable, paste(FigurePath, FocalTitle, " - Table", ".png", sep = ""))
    
# Combined Plot
  
  FocalCountsKableGrob <- tableGrob(FocalCounts, theme = ttheme_minimal())
    
  CombinedPlot <- 
    ggpubr::ggarrange(CountPlot, PercPlot, FocalCountsKableGrob, nrow = 3) 
  
  ComboTitle <- paste(BaseTitle, " - Combination - ", level, sep = "")
  
    ggsave(paste(FigurePath, ComboTitle, ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 8, height = 8, units = c("in"),
       dpi = 300)
}

template <- paste("![](", FigurePath, ")", sep = "")
filestoshow <- paste(BaseTitle, " - ", 
                     "Combination - ", 
                     Levels, 
                     ".png",
                     sep = ""
                     )

Comparing Results

#########################################################

EngCombinedResults <-
  EngComponents2021 %>%
    mutate(Year = "2021") %>%
    mutate(Chinese = plyr::mapvalues(CandNum, from = Results2020$CandNum, to = Results2020$Chinese)) %>%
    dplyr::select(c("Chinese", "FullName", "CandNum", "Level", "Subject", "Course", "Teacher",
                    "SyllLetter", "Year")) %>%
    dplyr::rename(Letter = SyllLetter) %>%
    mutate(Combo = paste(Level, Subject, FullName, sep = "-")) %>%
    rbind.data.frame(EngResults2020) %>%
    mutate(Year = factor(Year, levels = c("2021", "2020"))) %>%
    unite(YearLevel, Year, Level, sep = " ", remove = FALSE )

FocalTitle  <- "Comparison of Results between 2020 and 2021"

FigurePath <- paste(here(), "/Figures/Overall/Comparison/", sep = "")
dir.create(FigurePath)
DataPath <- paste(here(), "/Data/Overall/Comparison/", sep = "")
dir.create(DataPath) 

#Counts Plot 
CountPlot  <- 
  ggplot(data= EngCombinedResults , aes(x=Letter, fill = Letter)) +
    geom_bar(stat = "count", width = 0.8) +
    scale_x_discrete(breaks = IGLetterBoundaries$Letter, limits = rev, drop = FALSE) +
    scale_y_continuous(breaks = c(0, 20, 40, 60, 80)) +
    scale_fill_lettergrades() +
    labs(x="Letter Grade", y="Count") +
    facet_grid(fct_relevel(Year, "2020", "2021") ~ Level) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper(FocalTitle, width = 60))

   ggsave(paste(FigurePath, FocalTitle, " - Counts",  ".png", sep = ""), 
       plot = CountPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 600)

#Percentage Plot
PercPlot  <-
  ggplot(data= EngCombinedResults , aes(x=Year, fill = Letter)) +
  geom_bar(position = "fill") +
  scale_fill_lettergrades() +  
  labs(x="", y="Cumulative Percentage") +
  facet_grid(. ~ Level) +
  coord_flip() +
  theme_alan() +
  theme(legend.position = "bottom") +
  guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade")) 

  ggsave(paste(FigurePath, FocalTitle, " - Percentage", ".png", sep = ""),
       plot = PercPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300)

#Kable
CountsTable <- 
  data.frame(table(EngCombinedResults$YearLevel, EngCombinedResults$Letter)) %>%
    separate(Var1, into = c("Year", "Level"), sep = " ", remove = FALSE)  

AS2020DF <- subset(CountsTable, Var1 == "2020 AS")
AS2021DF <- subset(CountsTable, Var1 == "2021 AS")
IG2020DF <- subset(CountsTable, Var1 == "2020 IG")
IG2021DF <- subset(CountsTable, Var1 == "2021 IG")
A22020DF <- subset(CountsTable, Var1 == "2020 A2")
A22021DF <- subset(CountsTable, Var1 == "2021 A2")

FocalCounts  <-
  cbind.data.frame(
    AS2020DF$Var2,
    IG2020DF$Freq, IG2021DF$Freq,
    AS2020DF$Freq, AS2021DF$Freq,
    A22020DF$Freq, A22021DF$Freq
  ) %>%
    setNames(c("Letter Grade", "IG2020", "IG2021", "AS2020", "AS2021", "A22020", "A22021")) %>%
    mutate(IG2020Perc = IG2020 / sum(IG2020)*100) %>%
    mutate(IG2021Perc = IG2021 / sum(IG2021)*100) %>%
    mutate(AS2020Perc = AS2020 / sum(AS2020)*100) %>%
    mutate(AS2021Perc = AS2021 / sum(AS2021)*100) %>%
    mutate(A22020Perc = A22020 / sum(A22020)*100) %>%
    mutate(A22021Perc = A22021 / sum(A22021)*100) %>%
    mutate(IGDiff = IG2021Perc - IG2020Perc) %>%
    mutate(ASDiff = AS2021Perc - AS2020Perc) %>%
    mutate(A2Diff = A22021Perc - A22020Perc) %>%
    mutate_if(is.double, round, 1) %>%
    dplyr::select(c("Letter Grade", 
             "IG2020", "IG2021","IG2020Perc", "IG2021Perc", "IGDiff",
             "AS2020", "AS2021","AS2020Perc", "AS2021Perc", "ASDiff",
             "A22020", "A22021","A22020Perc", "A22021Perc", "A2Diff"
             ))

write.csv(FocalCounts, paste(DataPath, FocalTitle, ".csv", sep = ""))

levels <- levels(EngCombinedResults$Level)

FocalCountsKable  <-
  FocalCounts  %>%
    dplyr::select(c("Letter Grade", "IG2020Perc", "IG2021Perc", "IGDiff", "AS2020Perc", "AS2021Perc", "ASDiff", "A22020Perc", "A22021Perc", "A2Diff")) %>%
    setNames(c("Letter Grade", "2020", "2021", "Diff", "2020", "2021", "Diff", "2020", "2021", "Diff")) %>%
      knitr::kable(caption = FocalTitle, row.names = F, align = "lccccccccc") %>%
        row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
            column_spec(1, width = "1.5cm") %>%
            column_spec(seq(from = 1, to = (1 + (length(levels)-1)*3), by= 3), border_right = T) %>%
              ### Can't Figure out how to add headers anything other than manually!
            add_header_above(c(" " = 1, "IGCSE" = 3, "AS Exams" = 3, "A2 Exams" = 3)) %>%
            kable_styling(full_width = FALSE, 
              bootstrap_options = c("striped", "hover", "condensed"),
              fixed_thead = TRUE, 
              position = "center")

  save_kable(FocalCountsKable, paste(FigurePath, FocalTitle, " - Table", ".png", sep = ""))

# Combined Plot
  
  FocalCountsKableGrob <- 
    FocalCounts %>%
      dplyr::select(c("Letter Grade", 
             "IG2020Perc", "IG2021Perc", "IGDiff",
             "AS2020Perc", "AS2021Perc", "ASDiff",
             "A22020Perc", "A22021Perc", "A2Diff"
             )) %>%
      setNames(c("Letter Grade", 
                 "IG-2020", "IG-2021", "IG-Diff", 
                 "AS-2020", "AS-2021", "AS-Diff", 
                 "A2-2020", "A2-2021", "A2-Diff")) %>%
      tableGrob(theme = ttheme_minimal())
    
  CombinedPlot <- 
    ggpubr::ggarrange(CountPlot, PercPlot, FocalCountsKableGrob, nrow = 3) 
  
  ComboTitle <- paste(FocalTitle, " - Combination", sep = "")
  
    ggsave(paste(FigurePath, ComboTitle, ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 8, height = 8, units = c("in"),
       dpi = 300)

Comparison by Subject

We can, of course, take a look at this same plot broken down by each of the subjects as well

Subjects <- levels(EngCombinedResults$Subject)

FigurePath <- paste(here(), "/Figures/Course/Comparison/", sep = "")
dir.create(FigurePath)
DataPath <- paste(here(), "/Data/Course/Comparison/", sep = "")
dir.create(DataPath)
BaseTitle <- "Comparison between 2020 and 2021 -"

for (subject in Subjects){
  
    FocalTitle <- paste(BaseTitle, subject, sep = " ")
  FigurePathSubj <- paste(here(), "/Figures/Course/Comparison/", subject, "/", sep = "")
  dir.create(FigurePathSubj)

  FocalData <- subset(EngCombinedResults, Subject == subject)

#Counts Plot
  CountPlot <-
    ggplot(data= FocalData , aes(x=Letter, fill = Letter)) +
    geom_bar(stat = "count", width = 0.8) +
    scale_x_discrete(breaks = FocalLetters, limits = rev, drop = FALSE) +
    scale_y_continuous(breaks = c(0, 5, 10, 15, 20, 25, 30, 35, 40)) +
    scale_fill_lettergrades() +  
    labs(x="Letter Grade", y="Count") +
    facet_grid(fct_relevel(Year, "2020", "2021") ~ Level) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper(FocalTitle, width = 60))

   ggsave(paste(FigurePathSubj, FocalTitle, " - Counts",  ".png", sep = ""), 
    plot = CountPlot, device = NULL, path = NULL,
    width = 8, height = 3, units = c("in"),
    dpi = 300)
   
#Percentage Plot
  PercPlot  <-
    ggplot(data= FocalData , aes(x=Year, fill = Letter)) +
    geom_bar(position = "fill") +
    scale_fill_lettergrades() +  
    labs(x="", y="Cumulative Percentage") +
    facet_grid(Subject ~ Level, scales = "free") +
    coord_flip() +
    theme_alan() +
    theme(legend.position = "bottom") +
    guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade"))  

  ggsave(paste(FigurePathSubj, FocalTitle, " - Percentage", ".png", sep = ""),
       plot = PercPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300) 

#Kable

  FocalCounts <-
    data.frame(table(FocalData$YearLevel, FocalData$Letter)) %>%
      separate(Var1, into = c("Year", "Level"), sep = " ", remove = FALSE)  

  IG2020 <- subset(FocalCounts, Var1 == "2020 IG")
  IG2021 <- subset(FocalCounts, Var1 == "2021 IG")
  AS2020 <- subset(FocalCounts, Var1 == "2020 AS")
  AS2021 <- subset(FocalCounts, Var1 == "2021 AS")
  A22020 <- subset(FocalCounts, Var1 == "2020 A2")
  A22021 <- subset(FocalCounts, Var1 == "2021 A2")

  FocalCounts <- 
       qpcR:::cbind.na(AS2020$Var2, IG2020$Freq, IG2021$Freq, AS2020$Freq, AS2021$Freq, A22020$Freq, A22021$Freq) %>%
        data.frame() %>%
        setNames(c("Letter Grade", "IG2020", "IG2021", "AS2020", "AS2021", "A22020", "A22021")) %>%
        mutate(IG2020Perc = IG2020 / sum(IG2020)*100) %>%
        mutate(IG2021Perc = IG2021 / sum(IG2021)*100) %>%
        mutate(AS2020Perc = AS2020 / sum(AS2020)*100) %>%
        mutate(AS2021Perc = AS2021 / sum(AS2021)*100) %>%
        mutate(A22020Perc = A22020 / sum(A22020)*100) %>%
        mutate(A22021Perc = A22021 / sum(A22021)*100) %>%
        mutate(ASDiff = AS2021Perc - AS2020Perc) %>%
        mutate(A2Diff = A22021Perc - A22020Perc) %>%
        mutate(IGDiff = IG2021Perc - IG2020Perc) %>%   
        mutate_all(funs(replace_na(.,0)))%>% 
        dplyr::select(c("Letter Grade", 
                 "IG2020", "IG2021", "IG2020Perc", "IG2021Perc", "IGDiff",
                 'AS2020', 'AS2021', 'AS2020Perc', 'AS2021Perc', 'ASDiff', 
                 'A22020', 'A22021', 'A22020Perc', 'A22021Perc', 'A2Diff')) %>%  
        mutate_if(is.double, round, 1) 
    
        
    write.csv(FocalCounts, paste(DataPath, FocalTitle, ".csv", sep = ""))
        
    subjects <- levels(FocalData$Subject)

   FocalCountsKable <-
      FocalCounts %>%
        dplyr::select(c("Letter Grade", "IG2020Perc", "IG2021Perc", "IGDiff", "AS2020Perc", "AS2021Perc", "ASDiff", "A22020Perc", "A22021Perc", "A2Diff")) %>%
        setNames(c("Letter Grade", "2020", "2021", "Diff", "2020", "2021", "Diff", "2020", "2021", "Diff")) %>%
          knitr::kable(caption = FocalTitle, row.names = F, align = "lcccccc") %>%
            row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
              column_spec(1, width = "1.5cm") %>%
              column_spec(seq(from = 1, to = (1 + (length(subject)-1)*3), by= 3), border_right = T) %>%
              ### Can't Figure out how to add headers anything other than manually!
              add_header_above(c(" " = 1, "IG Exams" = 3, "AS Exams" = 3, "A2 Exams" = 3)) %>%
              kable_styling(full_width = FALSE, 
                bootstrap_options = c("striped", "hover", "condensed"),
                fixed_thead = TRUE, 
                position = "center")
        
    save_kable(FocalCountsKable, paste(FigurePathSubj, FocalTitle, " - Table", ".png", sep = ""))
    
  FocalCountsKableGrob <- 
    FocalCounts %>%
      setNames(c("Letter Grade", "IG-2020", "IG-2021", "IG-Diff", "AS-2020", "AS-2021", "AS-Diff", "A2-2020", "A2-2021", "A2-Diff")) %>%
      tableGrob(theme = ttheme_minimal())
    

# Combined Plot
  
  CombinedPlot <- 
    ggpubr::ggarrange(CountPlot, PercPlot, FocalCountsKableGrob, nrow = 3) 
  
  ComboTitle <- paste(FocalTitle, " - Combination", sep = "")
  
    ggsave(paste(FigurePath, ComboTitle, ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 8, height = 8, units = c("in"),
       dpi = 300)
    
}

template <- paste("![](", FigurePath, ")", sep = "")
filestoshow <- paste(BaseTitle, " " ,
                     Subjects,
                     " - Combination", 
                     ".png",
                     sep = ""
                     )
Courses <- levels(EngResults2020$Course)

for (course in Courses){
  
  FocalLevel <- as.data.frame(str_split(course, " "))[1,]
  FocalSubject <- as.data.frame(str_split(course, " "))[2,]
  
  if (FocalLevel == "IG"){FocalLetters <- factor(IGLetterBoundaries$Letter, levels = c("A*", "A", "B", "C", "D", "E", "F", "G", "U"))}
  if (FocalLevel == "AS"){FocalLetters <- factor(ASLetterBoundaries$Letter, levels = c("A", "B", "C", "D", "E", "U"))}
  if (FocalLevel == "A2"){FocalLetters <- factor(A2LetterBoundaries$Letter, levels = c("A*", "A", "B", "C", "D", "E", "U"))}

  FocalData <- 
    EngResults2020 %>%
      subset(Course == course) %>%
      mutate(Letter = factor(Letter, levels = FocalLetters)) 
  
  BaseTitle <- "2020 Results"
  FocalTitle <- paste(BaseTitle, " - ", course, sep = "")
  FigurePath <- paste(here(), "/Figures/Course/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Course/2020/", sep = "")
  dir.create(FigurePath)  
  FigurePathCourse <- paste(FigurePath, FocalSubject, "/", sep = "")
  dir.create(FigurePathCourse) 
  DataPath <- paste(here(), "/Data/Course/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Course/2020/", sep = "")
  dir.create(DataPath)

if (nrow(FocalData != 0)) {
# Count Plot
  CountPlot <-
    ggplot(data= FocalData , aes(x=Letter, fill = Letter)) +
      geom_bar(stat = "count", width = 0.8) +
      scale_x_discrete(breaks = levels(IGLetterBoundaries$Letter), limits = rev, drop = FALSE) +
      scale_y_continuous(breaks = c(0, 5, 10, 15, 20, 25, 30)) +
      scale_fill_lettergrades() +  
      labs(x="Letter Grade", y="Count") +
      theme_alan() +    
      theme(legend.position = "none") +
      ggtitle(wrapper(FocalTitle, width = 60))

  ggsave(paste(FigurePathCourse, FocalTitle, " - Counts", ".png", sep = ""), 
       plot = CountPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300)
  
# Percentage Plot
PercPlot <-
  ggplot(data= FocalData , aes(x= Level, fill = Letter)) +
  geom_bar(position = "fill") +
  scale_fill_lettergrades() +  
  labs(x="", y="Cumulative Percentage") +
  coord_flip() +
  theme_alan() +
  theme(legend.position = "bottom") +
  guides(fill = guide_legend(nrow=1, byrow=TRUE, title = "Letter Grade")) 

ggsave(paste(FigurePathCourse, FocalTitle, " - Percentage", ".png", sep = ""),
       plot = PercPlot, device = NULL, path = NULL,
       width = 8, height = 3, units = c("in"),
       dpi = 300)
 
# Counts Tables 
   FocalCounts <- 
    data.frame(table(FocalData$Letter)) %>%  
    setNames(c("Letter Grade", "Count")) %>%
    mutate(Percentage = Count/nrow(FocalData)*100) %>%
    mutate(Cumulative = cumsum(Percentage)) %>%
    mutate_if(is.double, round, 1)
  
  write.csv(FocalCounts, paste(DataPath, FocalTitle, ".csv", sep = ""))
  
  FocalCountsKable <-
    FocalCounts %>%
    knitr::kable(caption = FocalTitle, row.names = F) %>%
    row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
    kable_styling(full_width = FALSE, 
                  bootstrap_options = c("striped", "hover", "condensed"),
                  fixed_thead = TRUE)
  
  save_kable(FocalCountsKable, paste(FigurePathCourse, FocalTitle, " - Table", ".png", sep = ""))
  


  # Combined Plot
  
  FocalCountsKableGrob <- tableGrob(FocalCounts, theme = ttheme_minimal())
    
  CombinedPlot <- 
    ggpubr::ggarrange(CountPlot, PercPlot, FocalCountsKableGrob, nrow = 3) 
  
  ComboTitle <- paste(BaseTitle, " - Combination - ", course, sep = "")
  
    ggsave(paste(FigurePath, ComboTitle, ".png", sep = ""),
       plot = CombinedPlot, device = NULL, path = NULL,
       width = 8, height = 8, units = c("in"),
       dpi = 300)
    
    }
  
}

filestoshow <- 
    rev(paste("![](", list.files(FigurePath, pattern = "*Combination", full.names = TRUE), ")", sep = ""))

By Teacher

## We do not have 2020 Data by Teacher

The school has asked for tables like the one below.

Courses <- unique(EngCombinedResults$Course)
# course <- Courses[1]  #For testing. Commented out when not in use

for (course in Courses){

  BaseTitle <- "Results Comparison -"

  FigurePath <- paste(here(), "/Figures/Teacher/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Teacher/Comparison/", sep = "")
  dir.create(FigurePath)
  
  DataPath <- paste(here(), "/Data/Teacher/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/Comparison/", sep = "")
  dir.create(DataPath)

  # 2021 Counts
  FocalData2021 <- subset(EngCombinedResults, Course == course & Year == "2021")
  
  CountsT2021 <- 
    data.frame(table(FocalData2021$Letter)) %>%
    mutate(Perc = Freq/sum(Freq) *100)
  
  #2020 Counts
  FocalData2020 <- 
    subset(EngCombinedResults, Course == course & Year == "2020") %>%
    mutate(Teacher = "Unknown")
  
  CountsT2020 <- 
    data.frame(table(FocalData2020$Letter)) %>%
    mutate(Perc = Freq/sum(Freq) *100)
  
  FocalLevel <- unique(FocalData2021$Level)

  Teachers <- unique(FocalData2021$Teacher)
  # teacher <- Teachers[1]
  
  for (teacher in Teachers){
    
    FocalTitle <- paste(teacher, "-", BaseTitle, course)
    SchoolTitle <- paste(teacher, "-", BaseTitle, course, "-", "SchoolTable")
    
    FigurePathInd <- paste(FigurePath, teacher, "/", sep = "")
    dir.create(FigurePathInd) 
    
    DataPathInd <- paste(here(), "/Data/Teacher/Comparison/", teacher, "/", sep = "")
    dir.create(DataPathInd) 
    
    #Me2020
    FocalDataMe2020 <- subset(FocalData2020, Teacher == teacher)
        
    CountsMe2020 <-
      data.frame(table(FocalDataMe2020$Letter)) %>%
      mutate(Perc = Freq/sum(Freq) *100)
    
    #Me2021
    FocalDataMe2021 <- subset(FocalData2021, Teacher == teacher)
        
    CountsMe2021 <-
      data.frame(table(FocalDataMe2021$Letter)) %>%
      mutate(Perc = Freq/sum(Freq) *100)
    
    #NotMe2020
    FocalDataNotMe2020 <- subset(FocalData2020, Teacher != teacher)
        
    CountsNotMe2020 <-
      data.frame(table(FocalDataNotMe2020$Letter)) %>%
      mutate(Perc = Freq/sum(Freq) *100)
    
    #NotMe2021
    FocalDataNotMe2021 <- subset(FocalData2021, Teacher != teacher)
        
    CountsNotMe2021 <-
      data.frame(table(FocalDataNotMe2021$Letter)) %>%
      mutate(Perc = Freq/sum(Freq) *100)
    
##########################################################################################
### Setting Up The Large Main Table
    
    SchoolTable <-
      levels(IGLetterBoundaries$Letter) %>%
        cbind.data.frame(
          as.numeric(CountsMe2021$Freq), CountsMe2021$Perc, #Counts and Percentages for 2021 (Me)
          CountsNotMe2021$Perc, # Percentage for 2021 (NotMe)
          CountsMe2021$Perc, # Percentage for 2021 (Me)
          CountsMe2020$Perc, # Percentage for 2020 (Me)
          CountsMe2021$Perc, # Percentage for 2021 (Me)
          CountsNotMe2020$Perc # Percentage for 2020 (Not Me)
        ) %>%
      setNames(c("Letter Grade", 
                 "2021-Count-Mine", "2021-Perc-Mine",
                 "2021-Perc-Other", 
                 "2021-Perc-MineII", "2020-Perc-Mine",
                 "2021-Perc-MineIII", "2020-Perc-Other"
                 ) ) %>%
      mutate(Diff1 = `2021-Perc-Mine` - `2021-Perc-Other` ) %>%
      mutate(Diff2 = `2021-Perc-Mine` - `2020-Perc-Mine` ) %>%
      mutate(Diff3 = `2021-Perc-Mine` - `2020-Perc-Other` ) %>%
      select(c("Letter Grade", 
               "2021-Count-Mine", "2021-Perc-Mine", "2021-Perc-Other", "Diff1",
               "2021-Perc-MineII", "2020-Perc-Mine", "Diff2",
               "2021-Perc-MineIII", "2020-Perc-Other", "Diff3"
               )) %>%
      mutate_if(is.double, round, 1)
    
      write.csv(SchoolTable, paste(DataPathInd, FocalTitle, ".csv", sep = ""))
      
      totals <- c("Total", sum(SchoolTable$`2021-Count-Mine`), sum(SchoolTable$`2021-Perc-Mine`), sum(SchoolTable$`2020-Perc-Mine`), sum(SchoolTable$Diff2))
    
### Outputting as a pretty Kable    
  if (FocalLevel == "AS"){SchoolTable <- SchoolTable[c(2:6, 9),]}
  if (FocalLevel == "A2"){SchoolTable <- SchoolTable[c(1:6, 9),]}
      
  FocalCountsKable <-
    SchoolTable %>%
    setNames(c("Letter Grade", "Count", "% (Mine)", "% (Other)", "% Diff", "% (Mine)", "% (Mine)", "% Diff", "% (Mine)", "% (Other)", "% Diff")) %>%
    knitr::kable(caption = FocalTitle, row.names = F) %>%
    row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
    column_spec(c(1, 5, 8), border_right = T) %>%
    add_header_above(c(" " = 1, "2021" = 1, "2021" = 1, "2021" = 1, "Diff" = 1, "2021" = 1, "2020" = 1, "Diff" = 1, "2021" = 1, "2020" = 1, "Diff" = 1 )) %>%
    kable_styling(full_width = FALSE, 
      bootstrap_options = c("striped", "hover", "condensed"),
      fixed_thead = TRUE, 
      position = "center")
  
  save_kable(FocalCountsKable, paste(FigurePathInd, FocalTitle, " - Table", ".png", sep = ""))
      
##########################################################################################

##########################################################################################
### Setting Up The Alternative Table for new Teachers/Subjects
      
      SchoolTable3 <-
        SchoolTable %>%
          select(c("Letter Grade", "2021-Count-Mine", "2021-Perc-Mine", "2020-Perc-Other", "Diff3")) %>%
          rbind.data.frame(totals) %>%
          setNames(c("Grade", "Number of Students", "Percentage 2021", "Percentage 2020", "Difference"))
      
      write.csv(SchoolTable3, paste(DataPathInd, SchoolTitle, " II", ".csv", sep = ""))

### Outputting as a pretty Kable  
      
  if (FocalLevel == "AS"){SchoolTable3 <- SchoolTable3[c(2:6, 9),]}
  if (FocalLevel == "A2"){SchoolTable3 <- SchoolTable3[c(1:6, 9),]}
  
    FocalCountsKable3 <-
    SchoolTable3 %>%
    knitr::kable(caption = FocalTitle, row.names = F) %>%
    row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
      footnote(general = "Teacher data was not available for 2020, so comparisons are made to percentages of all students from 2020, rather than to a specific teacher's performance in the previous year") %>%
    kable_styling(full_width = FALSE, 
      bootstrap_options = c("striped", "hover", "condensed"),
      fixed_thead = TRUE, 
      position = "center")
  
  save_kable(FocalCountsKable3, paste(FigurePathInd, SchoolTitle, " II", ".png", sep = ""))
    
      
  }
  
}

Comparison to Mock Exam Results

It also makes sense to compare the results of our CAIE exams to the Mock Exam results, and in fact this is one of the tables that the school asks us to produce:

The table the school asks for is by-student, but it probably makes sense to first start with some summary data

### Assigning Letter Grades for IG
EngMock2021IG <- 
  EngMock2021 %>%
    subset(Level == "IG") %>%
    mutate(MockLetter = cut(MockResult,
                        breaks = c(IGLetterBoundaries$Bottom, 100),
                        labels = map_df(IGLetterBoundaries, rev)$Letter)) 

### Assigning Letter Grades for AS
EngMock2021AS <- 
  EngMock2021 %>%
    subset(Level == "AS") %>%
    mutate(MockLetter = cut(MockResult,
                        breaks = c(ASLetterBoundaries$Bottom, 100),
                        labels = map_df(ASLetterBoundaries, rev)$Letter)) 

### Assigning Letter Grades for A2
EngMock2021A2 <- 
  EngMock2021 %>%
    subset(Level == "A2") %>%
    mutate(MockLetter = cut(MockResult,
                        breaks = c(A2LetterBoundaries$Bottom, 100),
                        labels = map_df(A2LetterBoundaries, rev)$Letter)) 

### Recombining and Tidying
EngMock2021 <-
  rbind.data.frame(EngMock2021IG, EngMock2021AS, EngMock2021A2) %>%
    mutate(MockLetter = factor(MockLetter, levels = levels(IGLetterBoundaries$Letter))) 

rm(EngMock2021IG, EngMock2021AS, EngMock2021A2)

### Combining with 2021 CAIE Grades

EngMock2021Combo <-
  EngComponents2021 %>%
    select(c("FullName", "CandNum", "Level", "Subject", "Course", "Teacher", "SyllLetter")) %>%
    mutate(Combo = factor(paste(Level, Subject, FullName, sep = "-"))) %>%
    mutate(MockLetter = plyr::mapvalues(Combo, from = EngMock2021$Combo, to = as.character(EngMock2021$MockLetter)))
  
### Separating to assign numerical "letter grades"

EngMock2021ComboIG <- 
  EngMock2021Combo %>%
    subset(Level == "IG") %>%
    mutate(CAIE = plyr::mapvalues(SyllLetter, from = IGLetterBoundaries$Letter, to = nrow(IGLetterBoundaries):1)) %>%
    mutate(Mock = plyr::mapvalues(MockLetter, from = IGLetterBoundaries$Letter, to = nrow(IGLetterBoundaries):1))  

EngMock2021ComboAS <- 
  EngMock2021Combo %>%
    subset(Level == "AS") %>%
    mutate(CAIE = plyr::mapvalues(SyllLetter, from = ASLetterBoundaries$Letter, to = nrow(ASLetterBoundaries):1)) %>%
    mutate(Mock = plyr::mapvalues(MockLetter, from = ASLetterBoundaries$Letter, to = nrow(ASLetterBoundaries):1))  

EngMock2021ComboA2 <- 
  EngMock2021Combo %>%
    subset(Level == "A2") %>%
    mutate(CAIE = plyr::mapvalues(SyllLetter, from = A2LetterBoundaries$Letter, to = nrow(A2LetterBoundaries):1)) %>%
    mutate(Mock = plyr::mapvalues(MockLetter, from = A2LetterBoundaries$Letter, to = nrow(A2LetterBoundaries):1))  
  

EngMock2021Combo <-
  rbind.data.frame(EngMock2021ComboIG, EngMock2021ComboAS, EngMock2021ComboA2) 

rm(EngMock2021ComboIG, EngMock2021ComboAS, EngMock2021ComboA2)

This requires reading in the Mock Exam Grades (done above), and converting all of them to Numerical Grades. Now that that’s done, we can take a look at some overall analysis, starting with looking at how well correlated Mock Exam and Actual Exam grades are across all levels

FocalTitle <- "Correlation of Mock and CAIE Results - Overall"

FigurePath <- paste(here(), "/Figures/Overall/Mock/", sep = "")
dir.create(FigurePath)

#Calculate Correlation

Corr1 <- cor.test(as.numeric(as.character(EngMock2021Combo$CAIE)), as.numeric(as.character(EngMock2021Combo$Mock)))
Corr1StatA <- "Pearson's product moment correlation:"
Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")
  
#Plot
CorrPlot <- 
  ggplot(data=EngMock2021Combo, aes(x=as.numeric(as.character(CAIE)), y = as.numeric(as.character(Mock)))) +
    geom_jitter(color = RDFZReds[2], size = 1) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
#   geom_label_repel(aes(label = CandNum)) +
    scale_x_continuous(breaks = 1:9, limits= c(1,9) ) +
    scale_y_continuous(breaks = 1:9, limits= c(1,9) ) +
    labs(x="CAIE Result", y="Mock Result") +
    annotate("text", x= 6.5, y = 4, label = wrapper(Corr1StatA, width = 20), hjust = 0, vjust = 0, fontface = "bold" ) +
    annotate("text", x= 6.5, y = 3.5, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 0, fontface = "italic" ) +
    annotate("text", x= 6.5, y = 3, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 0) +
    theme_alan() +
    ggtitle(wrapper(FocalTitle, width = 60))

#Save Plot
  ggsave(paste(FigurePath, FocalTitle, ".png", sep = ""),
    plot = CorrPlot, device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)

Above is the correlation of Mock Exam and CAIE exam grades - and the correlation is 0.8, which is strong, as can be seen in the graph. In fact for discrete data of this sort this correlation is very strong indeed. Please note that the points here are “jittered” - i.e. it’s actually only possible for pints to occur on the grid lines (as the numbers represent letter scores) - but in order to see all of the students I’ve opted to apply “jitter” to the points, which spreads them out randomly around where they should be.

We can also look at this on a by-level basis

FocalTitle <- "Correlation of Mock and CAIE Results by Level"

FigurePath <- paste(here(), "/Figures/Overall/Mock/", sep = "")
dir.create(FigurePath)

#Plot
CorrPlot <- 
  ggplot(data=EngMock2021Combo, aes(x=as.numeric(as.character(CAIE)), y = as.numeric(as.character(Mock)))) +
    geom_jitter(color = RDFZReds[2], size = 1) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
#   geom_label_repel(aes(label = CandNum)) +
    scale_x_continuous(breaks = 1:9, limits= c(1,9) ) +
    scale_y_continuous(breaks = 1:9, limits= c(1,9) ) +
    labs(x="CAIE Result", y="Mock Result", scale = "free") +
    facet_grid(.~Level) +
    theme_alan() +
    ggtitle(wrapper(FocalTitle, width = 60))

#Save Plot
  ggsave(paste(FigurePath, FocalTitle, ".png", sep = ""),
    plot = CorrPlot, device = NULL, path = NULL,
    width = 8, height = 3, units = c("in"),
       dpi = 300)

Above you can see the correlation plots for each level of class. This can (again) be further broken down by Course

FocalTitle <- "Correlation of Mock and CAIE Results by Course"

FigurePath <- paste(here(), "/Figures/Course/Mock/", sep = "")
dir.create(FigurePath)

#Plot
CorrPlot <- 
  ggplot(data=EngMock2021Combo, aes(x=as.numeric(as.character(CAIE)), y = as.numeric(as.character(Mock)))) +
    geom_jitter(color = RDFZReds[2], size = 1) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    #geom_label_repel(aes(label = CandNum)) +
    scale_x_continuous(breaks = 1:9, limits= c(1,9) ) +
    scale_y_continuous(breaks = 1:9, limits= c(1,9) ) +
    labs(x="CAIE Result", y="Mock Result", scale = "free") +
    facet_grid(Subject ~ Level) +
    theme_alan() +
    ggtitle(wrapper(FocalTitle, width = 60))

#Save Plot
  ggsave(paste(FigurePath, FocalTitle, ".png", sep = ""),
    plot = CorrPlot, device = NULL, path = NULL,
    width = 9, height = 9, units = c("in"),
       dpi = 300)

And finally, we can look at this for every combination of Course and Teacher.

FocalTitle <- "Correlation of Mock and CAIE Results by Course Teacher"

FigurePath <- paste(here(), "/Figures/Course/Mock/", sep = "")
dir.create(FigurePath)

#Plot
CorrPlot <- 
  ggplot(data=EngMock2021Combo, aes(x=as.numeric(as.character(CAIE)), y = as.numeric(as.character(Mock)))) +
    geom_jitter(color = RDFZReds[2], size = 1) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    #geom_label_repel(aes(label = CandNum)) +
    scale_x_continuous(breaks = 1:9, limits= c(1,9) ) +
    scale_y_continuous(breaks = 1:9, limits= c(1,9) ) +
    labs(x="CAIE Result", y="Mock Result", scale = "free") +
    facet_grid(Course ~ Teacher) +
    theme_alan() +
    ggtitle(wrapper(FocalTitle, width = 60))

#Save Plot
  ggsave(paste(FigurePath, FocalTitle, ".png", sep = ""),
    plot = CorrPlot, device = NULL, path = NULL,
    width = 16, height = 16, units = c("in"),
       dpi = 300)

Of course, at this point the graphs become too small to actually look at when they are put in a facet in this way (not to mention all of the empty facets), so lets look at them on an actual by-teacher basis

Courses <- unique(EngMock2021Combo$Course)
# course <- Courses[1]

for (course in Courses){
  
  BaseTitle <- paste("Correlation of Mock and CAIE Results -", course)
  
  FigurePath <- paste(here(), "/Figures/Teacher/", sep = "")
  dir.create(FigurePath)
  FigurePath <- paste(here(), "/Figures/Teacher/Mock/", sep = "")
  dir.create(FigurePath)
  
  DataPath <- paste(here(), "/Data/Teacher/", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/Mock/", sep = "")
  dir.create(DataPath)
  
  CourseData <- subset(EngMock2021Combo, Course == course)
  
  Teachers <- unique(CourseData$Teacher)
  # teacher <- Teachers[1]
  
  for (teacher in Teachers){
    
    FocalTitle <- paste(teacher, "-", BaseTitle)

    FigurePathInd <- paste(FigurePath, teacher, "/", sep = "")
    dir.create(FigurePathInd) 
    
    DataPathInd <- paste(DataPath, teacher, "/", sep = "")
    dir.create(DataPathInd) 
    
    FocalData <- subset(CourseData, Teacher == teacher)
    
    FocalLevel <- unique(FocalData$Level)
    
    #Calculate Correlation
     if (nrow(FocalData) > 4){
       Corr1 <- cor.test(as.numeric(as.character(FocalData$CAIE)), as.numeric(as.character(FocalData$Mock)))
        Corr1StatA <- "Pearson's product moment correlation:"
    Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
    Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")
     }
    
    if (nrow(FocalData) <= 4){
      Corr1StatA <- "Pearson's product moment correlation:"
      Corr1StatB <- "Too few observations to calculate correlation"
      Corr1StatC <- ""
     }
    
    #Set Breaks and Labels
    if (FocalLevel == "IG"){BreakList <- 1:9}
    if (FocalLevel == "IG"){LabelList <- rev(unique(IGLetterBoundaries$Letter))}
    if (FocalLevel == "AS"){BreakList <- 1:6}
    if (FocalLevel == "AS"){LabelList <- rev(unique(ASLetterBoundaries$Letter))}
    if (FocalLevel == "A2"){BreakList <- 1:7}
    if (FocalLevel == "A2"){LabelList <- rev(unique(A2LetterBoundaries$Letter))}
    
    # Define a position variable so our labels stay with our points
    pos <- position_jitter(width = 0.1, height = 0.1, seed = 69420)
    
    #Plot
    CorrPlot <- 
    ggplot(data=FocalData, aes(x=as.numeric(as.character(CAIE)), y = as.numeric(as.character(Mock)))) +
    geom_jitter(color = RDFZReds[2], size = 1, position = pos) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    geom_label_repel(aes(label = FullName, alpha = 0.8), position = pos) +
          scale_x_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
          scale_y_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
    labs(x="CAIE Result", y="Mock Result") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatA, width = 40), hjust = 0, vjust = 1.5, fontface = "bold") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 3, fontface = "italic" ) +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 4.5) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper(FocalTitle, width = 60))
    
    #Save Plot
    ggsave(paste(FigurePathInd, FocalTitle, ".png", sep = ""),
    plot = CorrPlot, device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)
    
    #Create Table
    FocalTable <-
      FocalData %>%
        select(c("FullName", "Mock", "CAIE")) %>%
        mutate(Mock = as.numeric(as.character(Mock))) %>%
        mutate(CAIE = as.numeric(as.character(CAIE))) %>%
        mutate(Difference = CAIE - Mock) %>%
        arrange(FullName)
    
    # Output As A CSV
    write.csv(FocalTable, paste(DataPathInd, FocalTitle, ".csv", sep = ""))
    
    # Create as a prettier Kable
    
    TotalRow <- c("", "", "Total", sum(FocalTable$Difference))
    
    FocalKable <-
      FocalTable %>%
        rbind.data.frame(TotalRow) %>%
        knitr::kable(caption = FocalTitle, row.names = F) %>%
        row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
        kable_styling(full_width = FALSE, 
        bootstrap_options = c("striped", "hover", "condensed"),
        fixed_thead = TRUE, 
        position = "center")
  
    save_kable(FocalKable, paste(FigurePathInd, FocalTitle, " - Table", ".png", sep = ""))  

  }

}  

These graphs/tables are now made for every combination of Teacher and course, and can be found in "./Teacher/Mock/YourName. The table is the same as the second one asked for by the school.

Component Grades

It also bears looking at associations between grades on the various components, to help direct the focus of future teaching.

This is a giant pain in the ass for English Department, because every course has different component numbers…. so we will just do it manually by course

#Trimmed Components (only letter grades)
EngComponents2021Trimmed <- 
  EngComponents2021 %>%
    select(c(Level, Subject, Course, Teacher, FullName, 
             Comp01Letter, Comp02Letter, Comp03Letter, Comp04Letter, 
             Comp12Letter, Comp13Letter,
             Comp22Letter, 
             Comp32Letter,
             Comp42Letter,
             Comp52Letter))
BreakList <- 1:8
LabelList <- rev(IGLetterBoundaries$Letter[2:9])

FocalData <-
  EngComponents2021Trimmed %>%
    subset(Course == "IG ESOL") %>%
    select_if(col_selector) %>%
      mutate(Comp12 = plyr::mapvalues(Comp12Letter, from = LabelList, to = BreakList)) %>%
      mutate(Comp22 = plyr::mapvalues(Comp22Letter, from = LabelList, to = BreakList)) %>%
      mutate(Comp32 = plyr::mapvalues(Comp32Letter, from = LabelList, to = BreakList)) %>%
      mutate(Comp42 = plyr::mapvalues(Comp42Letter, from = LabelList, to = BreakList)) %>%
      mutate(Comp52 = plyr::mapvalues(Comp52Letter, from = LabelList, to = BreakList)) 

FigurePath <- paste(here(), "/Figures/Overall/Components/", sep = "")
dir.create(FigurePath)
  
#Component 12 vs 32
 #Calculate Correlation
    Corr1 <- cor.test(as.numeric(as.character(FocalData$Comp12)), as.numeric(as.character(FocalData$Comp32)))
    Corr1StatA <- "Pearson's product moment correlation:"
    Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
    Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")

    # Define a position variable so our labels stay with our points
    pos <- position_jitter(width = 0.1, height = 0.1, seed = 69420)
    
    #Plot
  CorrPlot <- 
    ggplot(data=FocalData, aes(x=as.numeric(as.character(Comp12)), y = as.numeric(as.character(Comp32)))) +
    geom_jitter(color = RDFZReds[2], size = 1, position = pos) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    geom_label_repel(aes(label = FullName, alpha = 0.8), position = pos) +
          scale_x_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
          scale_y_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
    labs(x= "Component 12", y= "Component 32") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatA, width = 40), hjust = 0, vjust = 1.5, fontface = "bold") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 3, fontface = "italic" ) +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 4.5) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper("IG ESOL - Comparison of Components", width = 60))
    
   ggsave(paste(FigurePath, "IG ESOL - Comparison of Components - 12 vs 32.png", sep = ""),
    plot = CorrPlot , device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)
   
   
 #####################################################  
   #Component 12 vs 52
 #Calculate Correlation
    Corr1 <- cor.test(as.numeric(as.character(FocalData$Comp12)), as.numeric(as.character(FocalData$Comp52)))
    Corr1StatA <- "Pearson's product moment correlation:"
    Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
    Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")

    # Define a position variable so our labels stay with our points
    pos <- position_jitter(width = 0.1, height = 0.1, seed = 69420)
    
    #Plot
  CorrPlot <- 
    ggplot(data=FocalData, aes(x=as.numeric(as.character(Comp12)), y = as.numeric(as.character(Comp52)))) +
    geom_jitter(color = RDFZReds[2], size = 1, position = pos) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    geom_label_repel(aes(label = FullName, alpha = 0.8), position = pos) +
          scale_x_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
          scale_y_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
    labs(x= "Component 12", y= "Component 52") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatA, width = 40), hjust = 0, vjust = 1.5, fontface = "bold") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 3, fontface = "italic" ) +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 4.5) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper("IG ESOL - Comparison of Components", width = 60))
    
   ggsave(paste(FigurePath, "IG ESOL - Comparison of Components - 12 vs 52.png", sep = ""),
    plot = CorrPlot , device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)

   
   #####################################################  
   #Component 32 vs 52
 #Calculate Correlation
    Corr1 <- cor.test(as.numeric(as.character(FocalData$Comp32)), as.numeric(as.character(FocalData$Comp52)))
    Corr1StatA <- "Pearson's product moment correlation:"
    Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
    Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")

    # Define a position variable so our labels stay with our points
    pos <- position_jitter(width = 0.1, height = 0.1, seed = 69420)
    
    #Plot
  CorrPlot <- 
    ggplot(data=FocalData, aes(x=as.numeric(as.character(Comp32)), y = as.numeric(as.character(Comp52)))) +
    geom_jitter(color = RDFZReds[2], size = 1, position = pos) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    geom_label_repel(aes(label = FullName, alpha = 0.8), position = pos) +
          scale_x_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
          scale_y_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
    labs(x= "Component 32", y= "Component 52") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatA, width = 40), hjust = 0, vjust = 1.5, fontface = "bold") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 3, fontface = "italic" ) +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 4.5) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper("IG ESOL - Comparison of Components", width = 60))
    
   ggsave(paste(FigurePath, "IG ESOL - Comparison of Components - 32 vs 52.png", sep = ""),
    plot = CorrPlot , device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)
   
#####################################################  
   #Component 22 vs 42
 #Calculate Correlation
    Corr1 <- cor.test(as.numeric(as.character(FocalData$Comp22)), as.numeric(as.character(FocalData$Comp42)))
    Corr1StatA <- "Pearson's product moment correlation:"
    Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
    Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")

    # Define a position variable so our labels stay with our points
    pos <- position_jitter(width = 0.1, height = 0.1, seed = 69420)
    
    #Plot
  CorrPlot <- 
    ggplot(data=FocalData, aes(x=as.numeric(as.character(Comp22)), y = as.numeric(as.character(Comp42)))) +
    geom_jitter(color = RDFZReds[2], size = 1, position = pos) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    geom_label_repel(aes(label = FullName, alpha = 0.8), position = pos) +
          scale_x_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
          scale_y_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
    labs(x= "Component 22", y= "Component 42") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatA, width = 40), hjust = 0, vjust = 1.5, fontface = "bold") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 3, fontface = "italic" ) +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 4.5) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper("IG ESOL - Comparison of Components", width = 60))
    
   ggsave(paste(FigurePath, "IG ESOL - Comparison of Components - 22 vs 42.png", sep = ""),
    plot = CorrPlot , device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)

   #####################################################  
   #Component 22 vs 52
 #Calculate Correlation
    Corr1 <- cor.test(as.numeric(as.character(FocalData$Comp22)), as.numeric(as.character(FocalData$Comp52)))
    Corr1StatA <- "Pearson's product moment correlation:"
    Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
    Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")

    # Define a position variable so our labels stay with our points
    pos <- position_jitter(width = 0.1, height = 0.1, seed = 69420)
    
    #Plot
  CorrPlot <- 
    ggplot(data=FocalData, aes(x=as.numeric(as.character(Comp22)), y = as.numeric(as.character(Comp52)))) +
    geom_jitter(color = RDFZReds[2], size = 1, position = pos) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    geom_label_repel(aes(label = FullName, alpha = 0.8), position = pos) +
          scale_x_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
          scale_y_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
    labs(x= "Component 12", y= "Component 52") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatA, width = 40), hjust = 0, vjust = 1.5, fontface = "bold") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 3, fontface = "italic" ) +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 4.5) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper("IG ESOL - Comparison of Components", width = 60))
    
   ggsave(paste(FigurePath, "IG ESOL - Comparison of Components - 22 vs 52.png", sep = ""),
    plot = CorrPlot , device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)
   
   #####################################################  
   #Component 42 vs 52
 #Calculate Correlation
    Corr1 <- cor.test(as.numeric(as.character(FocalData$Comp42)), as.numeric(as.character(FocalData$Comp52)))
    Corr1StatA <- "Pearson's product moment correlation:"
    Corr1StatB <- paste("r = ", round(Corr1$estimate,2), sep = "")
    Corr1StatC <- paste("(t", Corr1$parameter, " = " , round(Corr1$statistic, 1), ", p = ", 
                    ifelse(Corr1$p.value>0.001, round(Corr1$p.value,3), "<0.001"), ")" , sep = "")

    # Define a position variable so our labels stay with our points
    pos <- position_jitter(width = 0.1, height = 0.1, seed = 69420)
    
    #Plot
  CorrPlot <- 
    ggplot(data=FocalData, aes(x=as.numeric(as.character(Comp42)), y = as.numeric(as.character(Comp52)))) +
    geom_jitter(color = RDFZReds[2], size = 1, position = pos) +
    geom_smooth(method = "lm", se = FALSE, size = 1.2, color = RDFZReds[4]) +
    geom_label_repel(aes(label = FullName, alpha = 0.8), position = pos) +
          scale_x_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
          scale_y_continuous(breaks = BreakList, labels = LabelList, limits = c(BreakList[1], BreakList[length(BreakList)])) +
    labs(x= "Component 12", y= "Component 52") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatA, width = 40), hjust = 0, vjust = 1.5, fontface = "bold") +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatB, width = 30), hjust = 0, vjust= 3, fontface = "italic" ) +
    annotate("text", x= 1, y = Inf, label = wrapper(Corr1StatC, width = 30), hjust = 0, vjust = 4.5) +
    theme_alan() +
    theme(legend.position = "none") +
    ggtitle(wrapper("IG ESOL - Comparison of Components", width = 60))
    
   ggsave(paste(FigurePath, "IG ESOL - Comparison of Components - 42 vs 52.png", sep = ""),
    plot = CorrPlot , device = NULL, path = NULL,
    width = 6, height = 6, units = c("in"),
       dpi = 300)

If anyone particularly wants these, I can re-create them for other courses. But currently I have only completed them for IG ESOL because it’s too complicated to create them for the other courses, especially if folks won’t actually look at them

BreakList <- 1:8
LabelList <- rev(IGLetterBoundaries$Letter[2:9])

IG2021Trimmed <-
  EngComponents2021Trimmed %>%
    subset(Level == "IG") %>%
      mutate(TeacherCombo = paste(Level, Subject, Teacher, sep = "-"))

IG2021Table <-
  IG2021Trimmed %>%
    select(c("TeacherCombo", "FullName", 
             "Comp01Letter", "Comp02Letter", "Comp03Letter", "Comp04Letter", "Comp12Letter",      
             "Comp13Letter", "Comp22Letter", "Comp32Letter", "Comp42Letter", "Comp52Letter")) %>%
          pivot_longer(cols = c("Comp01Letter", "Comp02Letter", "Comp03Letter", "Comp04Letter", "Comp12Letter",      
             "Comp13Letter", "Comp22Letter", "Comp32Letter", "Comp42Letter", "Comp52Letter")) %>%
        mutate(name = factor(name)) %>%
        mutate(TeacherCombo = factor(TeacherCombo)) %>%
        na_if("") %>%
        drop_na() %>%
        arrange(TeacherCombo, name) %>%
        mutate(value = factor(value, levels = LabelList))

IG2021Counts <-
  IG2021Table %>%
    dplyr::count(TeacherCombo, name, value, .drop = FALSE) %>%
      separate(TeacherCombo, into = c("Level", "Subject", "Teacher"), sep = "-", remove = FALSE)

IGCourses <- unique(IG2021Counts$TeacherCombo)
# course <- IGCourses[1]

for (course in IGCourses){
  
  FocalData <- subset(IG2021Counts, TeacherCombo == course)
  
  SubjectTitle <- paste(FocalData$Level[1], " ", FocalData$Subject[1], " - ", FocalData$Teacher[1],
                        sep = "")
  
  FocalTable <-
    cbind.data.frame(
      FocalData$value[1:8],
      FocalData$n[1:8],
      FocalData$n[9:16],
      FocalData$n[17:24],
      FocalData$n[25:32],
      FocalData$n[33:40],
      FocalData$n[41:48],
      FocalData$n[49:56],
      FocalData$n[57:64],
      FocalData$n[65:72],
      FocalData$n[73:80]
    ) %>%
    setNames(c("Letter Grade", "Component 01", "Component 02", "Component 03", "Component 04",
               "Component 12", "Component 13", "Component 22", "Component 32", "Component 42", "Component 52" )) %>%
  mutate_at(vars(-`Letter Grade`), funs(round(./sum(.),3)*100)) %>%
  select_if(~ !any(is.nan(.))) %>%
  map_df(rev)
  
  FigurePath <- paste(here(), "/Figures/Teacher/Components/", FocalData$Teacher[1], "/",  sep = "")
  dir.create(FigurePath)
  DataPath <- paste(here(), "/Data/Teacher/Components", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/Components/", FocalData$Teacher[1], "/", sep = "")
  dir.create(DataPath)
 
  # Output As A CSV
  write.csv(FocalTable, paste(DataPath, SubjectTitle, ".csv", sep = ""))

  # Create as a prettier Kable
    
    FocalKable <-
      FocalTable %>%
        knitr::kable(caption = SubjectTitle, row.names = F) %>%
        row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
        kable_styling(full_width = FALSE, 
        bootstrap_options = c("striped", "hover", "condensed"),
        fixed_thead = TRUE, 
        position = "center")
  
    save_kable(FocalKable, paste(FigurePath, SubjectTitle, " - Table", ".png", sep = ""))
  
  
}
BreakList <- 1:6
LabelList <- rev(ASLetterBoundaries$Letter)

AS2021Trimmed <-
  EngComponents2021Trimmed %>%
    subset(Level == "AS") %>%
      mutate(TeacherCombo = paste(Level, Subject, Teacher, sep = "-"))

AS2021Table <-
  AS2021Trimmed %>%
    select(c("TeacherCombo", "FullName", 
             "Comp01Letter", "Comp02Letter", "Comp03Letter", "Comp04Letter", "Comp12Letter",      
             "Comp13Letter", "Comp22Letter", "Comp32Letter", "Comp42Letter", "Comp52Letter")) %>%
          pivot_longer(cols = c("Comp01Letter", "Comp02Letter", "Comp03Letter", "Comp04Letter", "Comp12Letter",      
             "Comp13Letter", "Comp22Letter", "Comp32Letter", "Comp42Letter", "Comp52Letter")) %>%
        mutate(name = factor(name)) %>%
        mutate(TeacherCombo = factor(TeacherCombo)) %>%
        na_if("") %>%
        drop_na() %>%
        arrange(TeacherCombo, name) %>%
        mutate(value = factor(value, levels = LabelList))

AS2021Counts <-
  AS2021Table %>%
    dplyr::count(TeacherCombo, name, value, .drop = FALSE) %>%
      separate(TeacherCombo, into = c("Level", "Subject", "Teacher"), sep = "-", remove = FALSE)

ASCourses <- unique(AS2021Counts$TeacherCombo)
# course <- IGCourses[1]

for (course in ASCourses){
  
  FocalData <- subset(AS2021Counts, TeacherCombo == course)
  
  SubjectTitle <- paste(FocalData$Level[1], " ", FocalData$Subject[1], " - ", FocalData$Teacher[1],
                        sep = "")
  
  FocalTable <-
    cbind.data.frame(
      FocalData$value[1:6],
      FocalData$n[1:6],
      FocalData$n[7:12],
      FocalData$n[13:18],
      FocalData$n[19:24],
      FocalData$n[25:30],
      FocalData$n[31:36],
      FocalData$n[37:42],
      FocalData$n[43:48],
      FocalData$n[49:54],
      FocalData$n[55:60]
    ) %>%
    setNames(c("Letter Grade", "Component 01", "Component 02", "Component 03", "Component 04",
               "Component 12", "Component 13", "Component 22", "Component 32", "Component 42", "Component 52" )) %>%
  mutate_at(vars(-`Letter Grade`), funs(round(./sum(.),3)*100)) %>%
  select_if(~ !any(is.nan(.))) %>%
  map_df(rev)
  
  FigurePath <- paste(here(), "/Figures/Teacher/Components/", FocalData$Teacher[1], "/",  sep = "")
  dir.create(FigurePath)
  DataPath <- paste(here(), "/Data/Teacher/Components", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/Components/", FocalData$Teacher[1], "/", sep = "")
  dir.create(DataPath)
 
  # Output As A CSV
  write.csv(FocalTable, paste(DataPath, SubjectTitle, ".csv", sep = ""))

  # Create as a prettier Kable
    
    FocalKable <-
      FocalTable %>%
        knitr::kable(caption = SubjectTitle, row.names = F) %>%
        row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
        kable_styling(full_width = FALSE, 
        bootstrap_options = c("striped", "hover", "condensed"),
        fixed_thead = TRUE, 
        position = "center")
  
    save_kable(FocalKable, paste(FigurePath, SubjectTitle, " - Table", ".png", sep = ""))
  
  
}
BreakList <- 1:7
LabelList <- rev(A2LetterBoundaries$Letter)

A22021Trimmed <-
  EngComponents2021Trimmed %>%
    subset(Level == "A2") %>%
      mutate(TeacherCombo = paste(Level, Subject, Teacher, sep = "-"))

A22021Table <-
  A22021Trimmed %>%
    select(c("TeacherCombo", "FullName", 
             "Comp01Letter", "Comp02Letter", "Comp03Letter", "Comp04Letter", "Comp12Letter",      
             "Comp13Letter", "Comp22Letter", "Comp32Letter", "Comp42Letter", "Comp52Letter")) %>%
          pivot_longer(cols = c("Comp01Letter", "Comp02Letter", "Comp03Letter", "Comp04Letter", "Comp12Letter",      
             "Comp13Letter", "Comp22Letter", "Comp32Letter", "Comp42Letter", "Comp52Letter")) %>%
        mutate(name = factor(name)) %>%
        mutate(TeacherCombo = factor(TeacherCombo)) %>%
        na_if("") %>%
        drop_na() %>%
        arrange(TeacherCombo, name) %>%
        mutate(value = factor(value, levels = LabelList))

A22021Counts <-
  A22021Table %>%
    dplyr::count(TeacherCombo, name, value, .drop = FALSE) %>%
      separate(TeacherCombo, into = c("Level", "Subject", "Teacher"), sep = "-", remove = FALSE)

A2Courses <- unique(A22021Counts$TeacherCombo)
# course <- IGCourses[1]

for (course in A2Courses){
  
  FocalData <- subset(A22021Counts, TeacherCombo == course)
  
  SubjectTitle <- paste(FocalData$Level[1], " ", FocalData$Subject[1], " - ", FocalData$Teacher[1],
                        sep = "")
  
  FocalTable <-
    cbind.data.frame(
      FocalData$value[1:6],
      FocalData$n[1:6],
      FocalData$n[7:12],
      FocalData$n[13:18],
      FocalData$n[19:24],
      FocalData$n[25:30],
      FocalData$n[31:36],
      FocalData$n[37:42],
      FocalData$n[43:48],
      FocalData$n[49:54],
      FocalData$n[55:60]
    ) %>%
    setNames(c("Letter Grade", "Component 01", "Component 02", "Component 03", "Component 04",
               "Component 12", "Component 13", "Component 22", "Component 32", "Component 42", "Component 52" )) %>%
  mutate_at(vars(-`Letter Grade`), funs(round(./sum(.),3)*100)) %>%
  select_if(~ !any(is.nan(.))) %>%
  map_df(rev)
  
  FigurePath <- paste(here(), "/Figures/Teacher/Components/", FocalData$Teacher[1], "/",  sep = "")
  dir.create(FigurePath)
  DataPath <- paste(here(), "/Data/Teacher/Components", sep = "")
  dir.create(DataPath)
  DataPath <- paste(here(), "/Data/Teacher/Components/", FocalData$Teacher[1], "/", sep = "")
  dir.create(DataPath)
 
  # Output As A CSV
  write.csv(FocalTable, paste(DataPath, SubjectTitle, ".csv", sep = ""))

  # Create as a prettier Kable
    
    FocalKable <-
      FocalTable %>%
        knitr::kable(caption = SubjectTitle, row.names = F) %>%
        row_spec(0, bold = T, color = "white", background = RDFZReds[4])%>%
        kable_styling(full_width = FALSE, 
        bootstrap_options = c("striped", "hover", "condensed"),
        fixed_thead = TRUE, 
        position = "center")
  
    save_kable(FocalKable, paste(FigurePath, SubjectTitle, " - Table", ".png", sep = ""))
  
  
}