Created
February 10, 2019 21:28
-
-
Save chris-prener/8037219130443da1223babdb5a02579d to your computer and use it in GitHub Desktop.
Script for Creating Multiple Choice Exams
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Workflow for Creating Multiple Choice Exams | |
# This process creates a pseudo-random sample of correct answers, and then generates | |
# an exam based on a specified number of questions assigned to different sections of | |
# the course. | |
# Install Dependencies | |
# install.packages(c("dplyr", "purrr", "readr", "rlang")) | |
# Create | |
questions <- cp_create_questions(n = 45) | |
# Check to make sure distribution of answers is relatively proportional | |
table(questions$correct) | |
# Randomly assign questions to different sections | |
exam <- cp_create_exam(questions, | |
c("lecture1", "5"), | |
c("lecture2", "5"), | |
c("lecture3", "5"), | |
c("week3", "10"), | |
c("methods", "10"), | |
c("week4", "10")) | |
# check exam | |
exam | |
# save | |
readr::write_csv(exam, "exam.csv") | |
# primary function one - create table of randomly assigned answers a through d | |
cp_create_questions <- function(n){ | |
correct = NULL | |
# create data frame | |
key <- data.frame( | |
question = c(1:n), | |
correct = sample.int(4, n, replace = TRUE) | |
) | |
# convert values to letters | |
key %>% | |
dplyr::mutate(correct = as.character(correct)) %>% | |
dplyr::mutate(correct = dplyr::case_when( | |
correct == "1" ~ "a", | |
correct == "2" ~ "b", | |
correct == "3" ~ "c", | |
correct == "4" ~ "d" | |
)) %>% | |
dplyr::as_tibble() -> out | |
# return output | |
return(out) | |
} | |
# primary function two - assign sections to answers | |
cp_create_exam <- function(.data, ...){ | |
output <- NULL | |
# convert questions to test bank | |
bank <- .data | |
# store dots as list | |
list <- rlang::list2(...) | |
# iterate over test sections | |
for (i in seq_along(list)){ | |
# store section input | |
item <- list[i][[1]] | |
# draw questions from test bank | |
sample <- exam_section(bank, n = as.numeric(item[2])) | |
# add section name to each question | |
sample <- dplyr::mutate(sample, section = as.character(item[1])) | |
# update test bank to remove drawn questions | |
bank <- exam_update(bank, sample) | |
# store section tibble in list | |
output[[i]] <- dplyr::as_tibble(sample) | |
} | |
# reduce section list to single table, arrange | |
purrr::reduce(output, dplyr::bind_rows) %>% | |
dplyr::arrange(question) -> out | |
# return output | |
return(out) | |
} | |
# sub-function for cp_create_exam - draw from test bank to create section | |
exam_section <- function(.data, n){ | |
# randomly sample from test bank | |
out <- dplyr::sample_n(.data, size = n) | |
# return output | |
return(out) | |
} | |
# sub-function for cp_create_exam - update test bank to remove section questions | |
exam_update <- function(.data, section){ | |
# store question numbers | |
x <- section$question | |
# remove questions in new test section | |
out <- dplyr::filter(.data, (question %in% x) == FALSE) | |
# return output | |
return(out) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment