Skip to content

Instantly share code, notes, and snippets.

@chris-prener
Created February 10, 2019 21:28
Show Gist options
  • Save chris-prener/8037219130443da1223babdb5a02579d to your computer and use it in GitHub Desktop.
Save chris-prener/8037219130443da1223babdb5a02579d to your computer and use it in GitHub Desktop.
Script for Creating Multiple Choice Exams
# 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