R: Simplifying code to convert letter grades to numeric grades
r
Solution
I would rewrite your `convert_grades` function as follows:
convert_grades <- function(x) {
A <- factor(x, levels=c("A+", "A", "A-",
"B+", "B", "B-",
"C+", "C", "C-",
"D+", "D", "D-", "F"))
values <- c(4.3, 4, 3.7,
3.3, 3, 2.7,
2.3, 2, 1.7,
1.3, 1, 0.7, 0)
values[A]
}
Then, I would do the conversion like this:
num_grades <- grades
num_grades[] <- lapply(num_grades, convert_grades)
num_grades
final_exam quiz_avg homework_avg
1 2.0 4.0 4
2 1.7 2.7 4
3 1.3 3.3 4
4 3.3 3.3 4
5 0.0 3.3 4
6 3.0 3.7 4
Problem
I have written a function in R that will convert a data frame containing letter grades into numeric grades. I then use sapply() on each column of the data frame. Is there a simpler way to do this that doesn't require three separate calls of sapply? Is there a way to apply a function to every element of a data frame instead of every row or column? The source data, "grades", looks like this: ``` grades <- read.table("Grades.txt", header = TRUE) head(grades) final_exam quiz_avg homework_avg 1 C A A 2 C- B- A 3 D+ B+ A 4 B+ B+ A 5 F B+ A 6 B A- A ``` My "`convert_grades`" function looks like this: ``` convert_grades <- function(x) { if (x == "A+") { x <- 4.3 } else if (x == "A") { x <- 4 } else if (x == "A-") { x <- 3.7 } else if (x == "B+") { x <- 3.3 } else if (x == "B") { x <- 3 } else if (x == "B-") { x <- 2.7 } else if (x == "C+") { x <- 2.3 } else if (x == "C") { x <- 2 } else if (x == "C-") { x <- 1.7 } else if (x == "D+") { x <- 1.3 } else if (x == "D") { x <- 1 } else if (x == "D-") { x <- 0.7 } else if (x == "F") { x <- 0 } else { x <- NA } return(x) } ``` My current approach is as follows: ``` num_grades <- grades num_grades[, 1] <- sapply(grades[, 1], convert_grades) num_grades[, 2] <- sapply(grades[, 2], convert_grades) num_grades[, 3] <- sapply(grades[, 3], convert_grades) head(num_grades) final_exam quiz_avg homework_avg 1 2.0 4.0 4 2 1.7 2.7 4 3 1.3 3.3 4 4 3.3 3.3 4 5 0.0 3.3 4 6 3.0 3.7 4 ```