Skip to content

Instantly share code, notes, and snippets.

@benmarwick
Last active March 24, 2025 21:42
Show Gist options
  • Save benmarwick/c9179fdc13596a66598218ac301f09f3 to your computer and use it in GitHub Desktop.
Save benmarwick/c9179fdc13596a66598218ac301f09f3 to your computer and use it in GitHub Desktop.
Final grade calculations from a Canvas gradebook that uses an additive grading policy
## Introduction
# This code will take grades on the Canvas gradebook, and add up the individual
# assignments to get a final grade, according to the policy for the class, in this
# case, here https://docs.google.com/spreadsheets/d/1-6f7mpgStojP4Gb3mk2PSwupGY2MiSrnIDD_KlxxEzk/edit?gid=874302185#gid=874302185
## Get the Canvas gradebook
# Go to the Canvas course page, go to the gradebook for that
# course, click 'Actions' then 'Export'. That will download a CSV file to
# your computer. Move that file into the same folder as this R script file.
# Make sure that the assignment that we are updating is 'published' so
# we get the column in the exported gradebook
library(tidyverse)
# update the Canvas gradebook file name here (assuming we are starting in grading.Rproj)
canvas_gradebook <- "2025-03-24T1409_Grades-ARCHY_488_A.csv"
# check structure of the data
str(read_csv(canvas_gradebook))
# sum up the assignments in each group, and assign to totals
canvas_gradebook_totals_update <-
read_csv(canvas_gradebook) %>%
filter(!is.na(`SIS Login ID`)) %>%
select(-contains(c("Current Points",
"Final Points",
"Current Score",
"Unposted Current Score",
"Final Score",
"Unposted Final Score"))) %>%
mutate(across(c(6:ncol(.) & where(is.character)),
parse_number)) %>%
dplyr::rowwise() %>%
# now do the additive grade calculations, create new columns to hold the
# totals, 1:10 for ten weeks
mutate(`Total Labs` = sum(c_across(contains(str_c("Week ", 1:10, ": "))),
na.rm = TRUE)) %>%
mutate(`Total Final Project` = sum(c_across(contains(str_c("Step ", 1:10, ": "))),
na.rm = TRUE)) %>%
# deal with the max allowed from each category, indicated here:
# https://docs.google.com/spreadsheets/d/1-6f7mpgStojP4Gb3mk2PSwupGY2MiSrnIDD_KlxxEzk/edit?gid=874302185#gid=874302185
mutate(`Total Labs` = if_else(`Total Labs` > 3,
3, `Total Labs` )) %>%
mutate(`Total Final Project` = if_else(`Total Final Project` > 1,
1, `Total Final Project` )) %>%
select(Student,
ID,
`SIS User ID`,
`SIS Login ID`,
Section,
`Total Labs`,
`Total Final Project`
)
# take a look before we upload to Canvas, does it look ok?
view(canvas_gradebook_totals_update)
# See how their grade out of 4.0 is looking
canvas_gradebook_totals_update_out_of_four <-
canvas_gradebook_totals_update %>%
rowwise() %>%
mutate(total_out_of_4.0 = rowSums(across(starts_with("Total")),
na.rm = TRUE) ) %>%
mutate(total_out_of_4.0 = ifelse(total_out_of_4.0 > 4,
4,
total_out_of_4.0)) %>%
# round up, https://stackoverflow.com/a/12688836/1036500
mutate(total_out_of_4.0_rounded = janitor::round_half_up(total_out_of_4.0, 1))
# take a look
view(canvas_gradebook_totals_update_out_of_four)
canvas_gradebook_totals_update_out_of_four %>%
select(Student, total_out_of_4.0_rounded) %>% View
ggplot(canvas_gradebook_totals_update_out_of_four) +
aes(total_out_of_4.0_rounded) +
geom_histogram() +
ggtitle("ARCHY 488 SP23 Distribution of final grades") +
theme_minimal(base_size = 14) +
xlab("Final grade submitted to the registrar")+
xlim(2, 4.1)
# ---- export to CSV, and import this file to Canvas gradebook
write_csv(canvas_gradebook_totals_update,
"update_totals_upload_to_canvas_gradebook.csv")
# ---- export to CSV, and import this file to UW GradePage
canvas_gradebook_totals_update_out_of_four %>%
select(`SIS User ID`,
ImportGrade = total_out_of_4.0_rounded) %>%
write_csv("update_totals_upload_to_gradepage.csv")
# Go to canvas an import, then come back here and continue...
# delete all the CSV files in this directory so we have a clean slate ready for next week
map(fs::dir_ls( glob = "*.csv"), fs::file_delete)
## Introduction
# This code will take grades on the Canvas gradebook, and add up the individual
# assignments to get a final grade, according to the policy for the class, in this
# case, here https://docs.google.com/spreadsheets/d/1-6f7mpgStojP4Gb3mk2PSwupGY2MiSrnIDD_KlxxEzk/edit?gid=874302185#gid=874302185
## Get the Canvas gradebook
# Go to the Canvas course page, go to the gradebook for that
# course, click 'Actions' then 'Export'. That will download a CSV file to
# your computer. Move that file into the same folder as this R script file.
# Make sure that the assignment that we are updating is 'published' so
# we get the column in the exported gradebook
library(tidyverse)
# update the Canvas gradebook file name here (assuming we are starting in grading.Rproj)
canvas_gradebook <- "2025-03-24T0948_Grades-ARCHY_483_A.csv"
# check structure of the data
str(read_csv(canvas_gradebook))
# sum up the assignments in each group, and assign to totals
canvas_gradebook_totals_update <-
read_csv(canvas_gradebook) %>%
filter(!is.na(`SIS Login ID`)) %>%
select(-contains(c("Current Points",
"Final Points",
"Current Score",
"Unposted Current Score",
"Final Score",
"Unposted Final Score"))) %>%
mutate(across(c(6:ncol(.) & where(is.character)),
parse_number)) %>%
dplyr::rowwise() %>%
# now do the additive grade calculations, create new columns to hold the
# totals, 1:10 for ten weeks
mutate(`Total Seminar notes` = sum(c_across(contains(str_c("Seminar ", 1:10, ": "))),
na.rm = TRUE)) %>%
mutate(`Total Participation` = sum(c_across(contains(str_c("Lecture ", 1:10, " participation "))),
na.rm = TRUE)) %>%
mutate(`Total Quizzes` = sum(c_across(contains(c(str_c("Lecture ", 1:10, " quiz "),
"Syllabus Quiz"))),
na.rm = TRUE))%>%
mutate(`Total Final paper` = round(sum(c_across(starts_with("Final paper step")),
na.rm = TRUE), 1) ) %>%
# deal with the max allowed from each category, indicated here:
# https://docs.google.com/spreadsheets/d/1-6f7mpgStojP4Gb3mk2PSwupGY2MiSrnIDD_KlxxEzk/edit?gid=874302185#gid=874302185
# max is 1 for all assignment categories, so we count 1 as the max towards the final grade
mutate(`Total Seminar notes` = if_else(`Total Seminar notes` > 1,
1, `Total Seminar notes` )) %>%
mutate(`Total Participation` = if_else(`Total Participation` > 1,
1, `Total Participation` )) %>%
mutate(`Total Quizzes` = if_else(`Total Quizzes` > 1,
1, `Total Quizzes` )) %>%
mutate(`Total Final paper` = if_else(`Total Final paper` > 1,
1, `Total Final paper` )) %>%
select(Student,
ID,
`SIS User ID`,
`SIS Login ID`,
Section,
`Total Seminar notes`,
`Total Participation`,
`Total Quizzes`,
`Total Final paper`
)
# take a look before we upload to Canvas, does it look ok?
view(canvas_gradebook_totals_update)
# See how their grade out of 4.0 is looking
canvas_gradebook_totals_update_out_of_four <-
canvas_gradebook_totals_update %>%
rowwise() %>%
mutate(total_out_of_4.0 = rowSums(across(starts_with("Total")),
na.rm = TRUE) ) %>%
mutate(total_out_of_4.0 = ifelse(total_out_of_4.0 > 4,
4,
total_out_of_4.0)) %>%
# round up, https://stackoverflow.com/a/12688836/1036500
mutate(total_out_of_4.0_rounded = janitor::round_half_up(total_out_of_4.0, 1))
# take a look
view(canvas_gradebook_totals_update_out_of_four)
canvas_gradebook_totals_update_out_of_four %>%
select(Student, total_out_of_4.0_rounded) %>% View
ggplot(canvas_gradebook_totals_update_out_of_four) +
aes(total_out_of_4.0_rounded) +
geom_histogram() +
ggtitle("ARCHY 483 SP23 Distribution of final grades") +
theme_minimal(base_size = 14) +
xlab("Final grade submitted to the registrar")+
xlim(2, 4.1)
# ---- export to CSV, and import this file to Canvas gradebook
write_csv(canvas_gradebook_totals_update,
"update_totals_upload_to_canvas_gradebook.csv")
# ---- export to CSV, and import this file to UW GradePage
canvas_gradebook_totals_update_out_of_four %>%
select(`SIS User ID`,
ImportGrade = total_out_of_4.0_rounded) %>%
write_csv("update_totals_upload_to_gradepage.csv")
# Go to canvas an import, then come back here and continue...
# delete all the CSV files in this directory so we have a clean slate ready for next week
map(fs::dir_ls( glob = "*.csv"), fs::file_delete)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment