In this lab, we will continue to use the “grades” dataset that is posted on Moodle.

We added an “average” column and assigned standard grades using an if-else ladder. We also added a “standardize” column to the dataframe in class. This assigned z-scores (numbers on the standard normal curve) to all of the averages.

In case you don’t have it, here is the code that will add the average column.

setwd("C:/Users/ethan/Desktop")#put your own working directory here
grades<-read.csv("grades.csv")
grades$Average<-apply(grades[,3:6], MARGIN=1, FUN=mean)

And here is the code that create the “standardize” function, and added it as a column to our dataset. Remember that to standardize an x value, we find the z-value, given by \(z=(x-\mu)/\sigma\). (Hold your cursor over this formula to see it for real–or, knit the file!)

standardize<-function(x){
  return((x-mean(x))/sd(x))
}
grades$Standardize<-standardize(grades$Average)

Go ahead and view the now-altered “grades” dataset to see exactly what is in it.

As a first exercise, let’s try “grading on a curve”. This assumes that if we gave the same course over and over again, the resulting grades would follow a normal distribution! We’ll assign grades as follows:

90th percentile and higher: A 80th percentile to 90th: B 70th percentile to 80th: C 60th percentile to 70th: D Below: F

As discussed in class, we can find the 90th percentile on the standard normal curve (centered at 0, standard deviation 1), with the command:

qnorm(.9)
## [1] 1.281552
?qnorm
## starting httpd help server ... done
  1. Find the 80th, 70th, 60th, percentiles using similar commands.
qnorm(.8)
## [1] 0.8416212
qnorm(.7)
## [1] 0.5244005
qnorm(.6)
## [1] 0.2533471
  1. Now write a new if-else ladder than assigns letter grades based on which percentile your standardized score falls into. (Look at how we assigned letter grades earlier for the general form of the if-else ladder.) When you are done, use the “head” function in R to display the top 10 lines of the grades dataset, so I can see how you assigned grades. (Please look at the knitted file to see that I will be able to see it!)
lettergrades <- c("replaceThis")
for (i in 1:length(grades[,1])){
  if (grades$Standardize[i]>=qnorm(.9)){
    lettergrades[i]<-"A"
  }else if (grades$Standardize[i]>=qnorm(.8)){
    lettergrades[i]<-"B"
  }else if (grades$Standardize[i]>=qnorm(.7)){
    lettergrades[i]<-"C"
  }else if (grades$Standardize[i]>=qnorm(.6)){
    lettergrades[i]<-"D"
  }else{
    lettergrades[i]<-"F"
  }
}
grades["lettergrade"]<-lettergrades
head(grades, 10)
##     X Student Exam.1 Exam.2 Exam.3 Project Average Standardize lettergrade
## 1   1    Abby     63     81     87      51   70.50 -0.39730623           F
## 2   2     Ben     54     67     73     100   73.50 -0.03904165           F
## 3   3   Chris     78     78     61      90   76.75  0.34907831           D
## 4   4   David     81     99     71      84   83.75  1.18502900           B
## 5   5   Ellen     74     60     62      76   68.00 -0.69586005           F
## 6   6   Frank     56     93     51      96   74.00  0.02066911           F
## 7   7     Gus     55     72     75      70   68.00 -0.69586005           F
## 8   8   Harry     82     54     72      66   68.50 -0.63614929           F
## 9   9     Ivy     87     52     55      56   62.50 -1.35267845           F
## 10 10    Jack     98     73     79      98   87.00  1.57314896           A

OK! Maybe I’d like to assign grades differently again.

  1. Use the “apply” function to add another column: “min”–meaning, this column should be the minimum grade the student earned in any of the columns Exam 1, Exam 2, Exam 3, and Project. Use the “head” function to display the first few lines of the resulting dataframe.
?apply
apply(X = grades[, 3:6], MARGIN = 1, FUN = min)
##  [1] 51 54 61 71 60 51 55 54 52 73 58 62 57 50 55 52 55 63 59 67 89 59 54 51 81
## [26] 50
testGrades<- grades
testGrades["min"] <- apply(X = grades[, 3:6], MARGIN = 1, FUN = min)
head(testGrades)
##   X Student Exam.1 Exam.2 Exam.3 Project Average Standardize lettergrade min
## 1 1    Abby     63     81     87      51   70.50 -0.39730623           F  51
## 2 2     Ben     54     67     73     100   73.50 -0.03904165           F  54
## 3 3   Chris     78     78     61      90   76.75  0.34907831           D  61
## 4 4   David     81     99     71      84   83.75  1.18502900           B  71
## 5 5   Ellen     74     60     62      76   68.00 -0.69586005           F  60
## 6 6   Frank     56     93     51      96   74.00  0.02066911           F  51
grades["min"] <- apply(X = grades[, 3:6], MARGIN = 1, FUN = min)
  1. Write a function that computes a “modified average”-the average a student makes if I drop the min score found above. (Try writing a function that takes 5 vector inputs: v1, v2,v3, v4, v5, and returns the average required ).
print("I don't know why you'd want five vector inputs, I'm gonna go ahead and write my own function")
## [1] "I don't know why you'd want five vector inputs, I'm gonna go ahead and write my own function"
modifyAverage <- function(student){
  scores <-  c(student[,3],student[,4],student[,5],student[,6])
  threeHighest<-(sort(scores)[2:4])
  return(as.numeric(sum(threeHighest)/3))
}
  1. Test the above function by applying it to vectors in your dataframe.

Once you think it works correctly, add another column to your dataframe that is the modified average (the average without the minimum grade). Again, display the top 10 lines of the dataframe so we can see your results.

modifiedaverage<-c("replaceThis")
for(rownumber in 1:length(grades[,1])){
  currentStudent <- grades[rownumber,]
  modifiedaverage[rownumber]<-modifyAverage(currentStudent)

}
grades["modified average"]<- modifiedaverage
head(grades)
##   X Student Exam.1 Exam.2 Exam.3 Project Average Standardize lettergrade min
## 1 1    Abby     63     81     87      51   70.50 -0.39730623           F  51
## 2 2     Ben     54     67     73     100   73.50 -0.03904165           F  54
## 3 3   Chris     78     78     61      90   76.75  0.34907831           D  61
## 4 4   David     81     99     71      84   83.75  1.18502900           B  71
## 5 5   Ellen     74     60     62      76   68.00 -0.69586005           F  60
## 6 6   Frank     56     93     51      96   74.00  0.02066911           F  51
##   modified average
## 1               77
## 2               80
## 3               82
## 4               88
## 5 70.6666666666667
## 6 81.6666666666667
  1. Assign “modified letter grade” column: use the above if-else ladder to assign new letter grades based upon the modified average instead. Is there a significant difference?
newstan<- c("replaceThis")
modifiedaverages<-grades["modified average"]
for (i in 1:length(grades["modified average"])){
  newstan[i]<- modifiedaverages[i]
}
grades["modified standardized"]<-standardize(as.numeric(newstan[[1]]))

lettergrades <- c("replaceThis")
for (i in 1:length(grades[,1])){
  if (grades$`modified standardized`[i]>=qnorm(.9)){
    lettergrades[i]<-"A"
  }else if (grades$`modified standardized`[i]>=qnorm(.8)){
    lettergrades[i]<-"B"
  }else if (grades$`modified standardized`[i]>=qnorm(.7)){
    lettergrades[i]<-"C"
  }else if (grades$`modified standardized`[i]>=qnorm(.6)){
    lettergrades[i]<-"D"
  }else{
    lettergrades[i]<-"F"
  }
}
grades["modified letter grade"]<-lettergrades
head(grades, 10)
##     X Student Exam.1 Exam.2 Exam.3 Project Average Standardize lettergrade min
## 1   1    Abby     63     81     87      51   70.50 -0.39730623           F  51
## 2   2     Ben     54     67     73     100   73.50 -0.03904165           F  54
## 3   3   Chris     78     78     61      90   76.75  0.34907831           D  61
## 4   4   David     81     99     71      84   83.75  1.18502900           B  71
## 5   5   Ellen     74     60     62      76   68.00 -0.69586005           F  60
## 6   6   Frank     56     93     51      96   74.00  0.02066911           F  51
## 7   7     Gus     55     72     75      70   68.00 -0.69586005           F  55
## 8   8   Harry     82     54     72      66   68.50 -0.63614929           F  54
## 9   9     Ivy     87     52     55      56   62.50 -1.35267845           F  52
## 10 10    Jack     98     73     79      98   87.00  1.57314896           A  73
##    modified average modified standardized modified letter grade
## 1                77            -0.1871698                     F
## 2                80             0.1550000                     F
## 3                82             0.3831131                     D
## 4                88             1.0674526                     B
## 5  70.6666666666667            -0.9095281                     F
## 6  81.6666666666667             0.3450943                     D
## 7  72.3333333333333            -0.7194338                     F
## 8  73.3333333333333            -0.6053772                     F
## 9                66            -1.4417922                     F
## 10 91.6666666666667             1.4856601                     A
#length(which(grades["modified letter grade"] == "F"))
#length(which(grades["lettergrade"] == "F"))
print("one fewer person gets an F")
## [1] "one fewer person gets an F"
#length(which(grades["modified letter grade"] == "D"))
#length(which(grades["lettergrade"] == "D"))
print("two more people get a D")
## [1] "two more people get a D"
#length(which(grades["modified letter grade"] == "C"))
#length(which(grades["lettergrade"] == "C"))
print("one fewer person gets a C")
## [1] "one fewer person gets a C"
#length(which(grades["modified letter grade"] == "B"))
#length(which(grades["lettergrade"] == "B"))
print("two fewer people get a B")
## [1] "two fewer people get a B"
#length(which(grades["modified letter grade"] == "A"))
#length(which(grades["lettergrade"] == "A"))
print("two more people get an A")
## [1] "two more people get an A"
print("this is a significant difference for the folks bumped up from an F or B, but it sucks for that one person who gets bumped down from a C to a D")
## [1] "this is a significant difference for the folks bumped up from an F or B, but it sucks for that one person who gets bumped down from a C to a D"