Title: | Grades Setting and Exam Maker |
---|---|
Description: | Programs to determine student grades and create examinations from Question banks. Programs will create numerous multiple choice exams, randomly shuffled, for different versions of same question list. |
Authors: | Jonathan M. Lees [aut, cre] |
Maintainer: | Jonathan M. Lees <[email protected]> |
License: | GPL (>= 2) |
Version: | 2.4-3 |
Built: | 2025-02-11 02:40:41 UTC |
Source: | https://github.com/cran/ProfessR |
Programs to determine student grades and create examinations from Question banks. Programs will create numerous multiple choice exams, randomly shuffled, for different versions of same question list.
Jonathan M. Lees
Maintainer: Jonathan M. Lees<[email protected]>
################ making tests: ## Not run: data(QBANK1) make.exam(QBANK1, ofile="exam1.tex") ## End(Not run) ################# setting grades: g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1")
################ making tests: ## Not run: data(QBANK1) make.exam(QBANK1, ofile="exam1.tex") ## End(Not run) ################# setting grades: g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1")
Automatically email a file to an address using the perl program.
autoemail(eadd, sfile, hnote = "Exam Results")
autoemail(eadd, sfile, hnote = "Exam Results")
eadd |
Email address |
sfile |
file to be sent |
hnote |
subject line |
This program will work well in Linux and Mac where Perl is installed - I am not sure about Windows. Creates a unix executable file, if perl is present.
Side Effects.
Need to change the from designation.
Jonathan M. Lees<[email protected]>
IDandEM
Sequentially check a set of Question banks. Makes sure there is a QUESTION: and ANSWER for each question.
CHECKbank(QB)
CHECKbank(QB)
QB |
list of question banks |
Printed Side Effects
Jonathan M. Lees<[email protected]>
seebank
data(QBANK1) CHECKbank(QBANK1) ############ modify by inserting an error: QBANK1[[4]]$numANS=NULL ### recheck: CHECKbank(QBANK1)
data(QBANK1) CHECKbank(QBANK1) ############ modify by inserting an error: QBANK1[[4]]$numANS=NULL ### recheck: CHECKbank(QBANK1)
View grades sorted and listed with raw score, letter and scaled score, with optional ID and name
checkgrades(D1, id = NULL, names = NULL)
checkgrades(D1, id = NULL, names = NULL)
D1 |
output of do.grades |
id |
character vector, ID for students |
names |
character vector, names of students |
Side effects
Jonathan M. Lees<[email protected]>
do.grades, DUMPgrades
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### to run interactively, remove the divs ### D1 = do.grades(g, tit="GEOL 105 Exam 1") ### otherwise use previously calculated divs: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") checkgrades(D1 )
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### to run interactively, remove the divs ### D1 = do.grades(g, tit="GEOL 105 Exam 1") ### otherwise use previously calculated divs: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") checkgrades(D1 )
Compare two question banks to find non-duplicated questions
COMPbank(Qbank1, Qbank2)
COMPbank(Qbank1, Qbank2)
Qbank1 |
Question Bank 1 |
Qbank2 |
Question Bank 2 |
Uses match to find matching questions in the two question banks.
Vector index of questions in Qbank2 that are not found in Qbank1.
Only the questions are compared, the answers are ingnored. The return vector will be a set of questions that are not duplicated, i.e. unique to question bank 2.
Jonathan M. Lees<[email protected]>
SELbank
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF Kbank = vector(mode='list') for(i in 1:length(kbank)) { Kbank = c(Kbank, kbank[[i]]) } q2 = COMPbank(Kbank, kbank[[3]] ) ########### to extract these: subq2 = subsetbank(kbank[[3]] , q2) ########### to get the overlapping questions: olap = 1:length(kbank[[3]]) olap[-q2] ## End(Not run)
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF Kbank = vector(mode='list') for(i in 1:length(kbank)) { Kbank = c(Kbank, kbank[[i]]) } q2 = COMPbank(Kbank, kbank[[3]] ) ########### to extract these: subq2 = subsetbank(kbank[[3]] , q2) ########### to get the overlapping questions: olap = 1:length(kbank[[3]]) olap[-q2] ## End(Not run)
Remove blanks from strings.
deblank(a)
deblank(a)
a |
Character string |
Removes all blanks from strings. The functuon works on vectors of strings, removing blanks on each element.
Character string with no blanks.
Jonathan M. Lees<[email protected]>
j = c(' James', 'Jones ', 'Alpha Dog') deblank(j)
j = c(' James', 'Jones ', 'Alpha Dog') deblank(j)
Calculate the grades of a class of students, given raw scores on exam
do.grades(ggrades, divs = NULL, cut = 0, tit = "Exam Grades", breaks=length(ggrades)/3, ...)
do.grades(ggrades, divs = NULL, cut = 0, tit = "Exam Grades", breaks=length(ggrades)/3, ...)
ggrades |
Raw grades |
divs |
divisions for grades (optional) |
cut |
low end Cut off to remove 0 from statistics |
tit |
Title for Figure |
breaks |
breaks for the histogram, default=length(ggrades)/3 |
... |
other parameters for hist |
To remove students who do not take the test a low end cut off is used to excise any grades below that level. Both mean, and standard deviations are shown as well as median and quartiles.
grades=ggrades, lett=letts, scor=scores, divs=divs, LETS=LETS, SCRS=SCRS, hist=HA LIST:
grades |
raw scores |
lett |
letter grades |
scor |
scaled grades |
divs |
divisions, estimated by user or provided as input |
LETS |
letter grades assigned |
SCRS |
Scores related to LETS |
hist |
histogram structure |
Grades are determined linearly within a division
Jonathan M. Lees<[email protected]>
jist, DUMPgrades, getlet
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) ########## set divisions automatically: divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### to run interactively, remove the divs ### D1 = do.grades(g, tit="GEOL 105 Exam 1") ### otherwise use previously calculated divs: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") ## Not run: #### this is interactive D1 = do.grades(g, tit="GEOL 105 Exam 1") ####### list the grades: cbind(D1$grades, D1$lett, D1$scor) ####### if you have names or ID's try: ####### cbind(IDs, D1$grades, D1$lett, D1$scor) \dontrun{ DUMPgrades(D1, file="TEST1grades", id=IDS ) } ## End(Not run)
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) ########## set divisions automatically: divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### to run interactively, remove the divs ### D1 = do.grades(g, tit="GEOL 105 Exam 1") ### otherwise use previously calculated divs: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") ## Not run: #### this is interactive D1 = do.grades(g, tit="GEOL 105 Exam 1") ####### list the grades: cbind(D1$grades, D1$lett, D1$scor) ####### if you have names or ID's try: ####### cbind(IDs, D1$grades, D1$lett, D1$scor) \dontrun{ DUMPgrades(D1, file="TEST1grades", id=IDS ) } ## End(Not run)
Drop the lowest grade from a matrix of grades. Matrix is assumed to be N by m where m is the number of exams (columns), N the number of students (rows)
droplowest(z)
droplowest(z)
z |
Matrix of scores, rows are students, columns are exam scores |
Best matrix output is sorted, so the grades do not reflect the original order of exam scores. To drop the two lowest scores, apply this program twice, running it a second time on the best outut.
minind |
Index of minimum score |
best |
matrix of scores with the lowest dropped |
midgrade |
mean value of best scores |
Jonathan M. Lees<[email protected]>
do.grades
######### generate fake exam scores, 10 students, 3 exams z = matrix(runif(3*10, 50, 100), ncol=3 ) A = droplowest(z) cbind(A$best, A$minind, z, A$midgrade)
######### generate fake exam scores, 10 students, 3 exams z = matrix(runif(3*10, 50, 100), ncol=3 ) A = droplowest(z) cbind(A$best, A$minind, z, A$midgrade)
Save an ASCII version of a selected Question Bank
DUMPbank(ofile, QB, sep = "\n", append=TRUE)
DUMPbank(ofile, QB, sep = "\n", append=TRUE)
ofile |
character, output file |
QB |
QuestionBank Structure |
sep |
separator between questions |
append |
logical, if FALSE a new file is created |
Side effects
Jonathan M. Lees<[email protected]>
Get.testbank
## Not run: data(QBANK1) DUMPbank("my.questions", QBANK1, sep = "\n") QB1=Get.testbank("my.questions") ## End(Not run)
## Not run: data(QBANK1) DUMPbank("my.questions", QBANK1, sep = "\n") QB1=Get.testbank("my.questions") ## End(Not run)
Dump grades to a file
DUMPgrades(D1, file = NULL, id = NULL, names = NULL)
DUMPgrades(D1, file = NULL, id = NULL, names = NULL)
D1 |
list output from do.grades |
file |
file name, a csv will be added as a suffix |
id |
vector of student IDs |
names |
character vector of student names |
Side effects
Jonathan M. Lees<[email protected]>
do.grades
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### to run interactively, remove the divs ### D1 = do.grades(g, tit="GEOL 105 Exam 1") ### otherwise use previously calculated divs: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") ## Not run: DUMPgrades(D1, file="TEST1grades" ) ## End(Not run)
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### to run interactively, remove the divs ### D1 = do.grades(g, tit="GEOL 105 Exam 1") ### otherwise use previously calculated divs: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") ## Not run: DUMPgrades(D1, file="TEST1grades" ) ## End(Not run)
Finds dupliucated questions in a set of Question Banks
DUPbank(Qbank)
DUPbank(Qbank)
Qbank |
a list of Question Banks |
The program only checks the questions, not the answers. One could thus have several questions with the same wording, but different answers. I might change this in the future. Given the list of duplicated questions one should edit the original question bank files to remove them.
A |
vector of duplicated questions |
F |
vector of duplicated files where the questions were extracted |
I |
vector of duplicated indexes where the questions were extracted |
N |
vector of duplicated indexes where the questions were extracted |
Jonathan M. Lees<[email protected]>
data(QBANK1) ### force some questions to be duplicates: QBANK1[[51]]=QBANK1[[25]] QBANK1[[52]]=QBANK1[[12]] QBANK1[[14]]=QBANK1[[4]] DQ = DUPbank(QBANK1) DQ
data(QBANK1) ### force some questions to be duplicates: QBANK1[[51]]=QBANK1[[25]] QBANK1[[52]]=QBANK1[[12]] QBANK1[[14]]=QBANK1[[4]] DQ = DUPbank(QBANK1) DQ
Real exam raw scores from test in Geology 105, University of North Carolina. Zeros are assigned to students who did not take the test.
data(E2grades)
data(E2grades)
numeric vector
data(E2grades) g = E2grades B = boxplot(g[g>1], plot=FALSE) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### get(getOption("device"))(width = 12, height = 7) D1 = do.grades(g, divs=divs, cut = 15, tit="GEOL 105 Exam 1") jist(D1$hist, D1$grades, D1$lett, col='purple')
data(E2grades) g = E2grades B = boxplot(g[g>1], plot=FALSE) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ### get(getOption("device"))(width = 12, height = 7) D1 = do.grades(g, divs=divs, cut = 15, tit="GEOL 105 Exam 1") jist(D1$hist, D1$grades, D1$lett, col='purple')
Statistical Analysis of Examination where the results are either correct or incorrect.
EXAMstats(j, key)
EXAMstats(j, key)
j |
matrix of student responses |
key |
key of correct answers |
At this statge no partial credit is given.
List
H |
Matrix: question, correct response, student responses, difficulty, Desc, BiSer |
kr20 |
Kruder-Richardson reliability statistic |
There is a slightly different implementation if partial credit is employed. See
Jonathan M. Lees<[email protected]>
Kuder, G. F., and Richardson, M. W. (1937). The theory of the estimation of test reliability. Psychometrika, 2(3), 151-160.
Cortina, J. M., (1993). What Is Coefficient Alpha? An Examination of Theory and Applications. Journal of Applied Psychology, 78(1), 98-104.
readSCANTRON
## Not run: B2 = readSCANTRON(rawfn2) Estat = EXAMstats(B2$studans, B2$key) Estat$kr20 ## End(Not run)
## Not run: B2 = readSCANTRON(rawfn2) Estat = EXAMstats(B2$studans, B2$key) Estat$kr20 ## End(Not run)
Fix names to remove problematic alphanumeric characters like spaces, quotes
fix.names(nam, upper=FALSE, lower=FALSE)
fix.names(nam, upper=FALSE, lower=FALSE)
nam |
string |
upper |
logical, TRUE= convert to upper case |
lower |
logical, TRUE= convert to lower case |
Currently only space, single and double quotes.
string, with quaote replaced with underscore
Jonathan M. Lees<[email protected]>
#### examples with embedded quotes are not available #### because they interfere with R documentation LAM = "SILENCED LAMB" fix.names(LAM, lower=TRUE) LAM = "Silence my Lamb" fix.names(LAM, upper=TRUE) LAM = "SILeNCED LAMB" fix.names(LAM) ### try with single quote LAM = "O'brian LAMB" fix.names(LAM)
#### examples with embedded quotes are not available #### because they interfere with R documentation LAM = "SILENCED LAMB" fix.names(LAM, lower=TRUE) LAM = "Silence my Lamb" fix.names(LAM, upper=TRUE) LAM = "SILeNCED LAMB" fix.names(LAM) ### try with single quote LAM = "O'brian LAMB" fix.names(LAM)
Get Test Bank From Ascii Text Files
Get.testbank(fn)
Get.testbank(fn)
fn |
File Name |
Structure of input file is strict: see the vignette for an example. Each questions starts with the tag QUESTION: (there is a space following the colon on all tags) followed by answers with the correct answer indicated by the tag ANSWER: . The tag FIG: allows the examiner to include a figure with a latex tag for reference. For example: ‘ QUESTION: What was the world like during the Late Paleocene Torrid Age? ANSWER: a. Most of the world was wetter and warmer. b. Most of the world was drier and warmer. c. Most of the world was wetter, but a little cooler. d. Most of the world was a desert. e. It is impossible to estimate conditions at that time. ’
List: list of Questions
Jonathan M. Lees<[email protected]>
## Not run: fn = "MY.questions" Qbank = Get.testbank(fn) ########## use existing database: data(QBANK1) ##### dump out question bank in correct format: DUMPbank("my.questions", QBANK1, sep = "\n") ### read it in: QB1=Get.testbank("my.questions") ## End(Not run)
## Not run: fn = "MY.questions" Qbank = Get.testbank(fn) ########## use existing database: data(QBANK1) ##### dump out question bank in correct format: DUMPbank("my.questions", QBANK1, sep = "\n") ### read it in: QB1=Get.testbank("my.questions") ## End(Not run)
Create groups of students and plot groups to screen.
getgroup(g.first, n = 2)
getgroup(g.first, n = 2)
g.first |
Character vector of student names. |
n |
number per group |
Class roster will be divided into n groups and displayed on the the screen.
List of groups with names.
The class is currently randomized in this version.
Jonathan M. Lees<[email protected]>
GetStudentNames
g.last =c('Joyce', 'Einstein', 'Hertz', 'Bailey', 'Compton', 'Jones', 'Wilson', 'Smith', 'Anderson' ) getgroup(g.last, n = 3)
g.last =c('Joyce', 'Einstein', 'Hertz', 'Bailey', 'Compton', 'Jones', 'Wilson', 'Smith', 'Anderson' ) getgroup(g.last, n = 3)
Read Key output
getKEY(fn)
getKEY(fn)
fn |
character string file name |
Reads in the file output of ProfessR and returns a vector of answers
vector of correct answers
Jonathan M. Lees<[email protected]>
version.exam, prep.solution
Get letter grades from list of numeric scores
getlet(ggrades, divs)
getlet(ggrades, divs)
ggrades |
vector of grades |
divs |
numerical vector of divisions |
Returns letter grades scaled linearly between divisions.
LIST:
ggrades |
Input grades |
lett |
letter values |
scor |
scores after scaling |
divs |
divisions used in setting scores |
LETS |
Letters for grades |
SCRS |
numeric divisions used for LETS |
olett |
letter values, older version |
oscor |
scores after scaling, older version binned |
Jonathan M. Lees<[email protected]>
do.grades
g = rnorm(130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) G = getlet(g, divs) cbind(G$LETS, G$SCRS) data.frame(G$grades, G$lett, G$scor)
g = rnorm(130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) G = getlet(g, divs) cbind(G$LETS, G$SCRS) data.frame(G$grades, G$lett, G$scor)
Given a roster of students, with (lastname, first name) format, extract a unique set of first names, with no blanks.
GetStudentNames(c1, dup.lets=1)
GetStudentNames(c1, dup.lets=1)
c1 |
Character vector |
dup.lets |
NUmber of letters to add from last name in the event that first names are duplicated. |
The function assumes the names are comma separated with lastname, firstname order. The code separates the names, removes blanks from the first name, and finds a unique set of names. If first names are not unique, the function extracts the first letters of the last names and the duplicated names and appends with a period.
Character vector of unique first names
Jonathan M. Lees<[email protected]>
g.first =c("Jason","Skyler","Adrian","Berkley","Jack",'David', 'David', 'Jim', 'Jim') g.last =c('Joyce', 'Einstein', 'Hertz', 'Bailey', 'Compton', 'Jones', 'Wilson', 'Smith', 'Anderson' ) c2 = paste(g.last, g.first, sep=', ') K = GetStudentNames(c2)
g.first =c("Jason","Skyler","Adrian","Berkley","Jack",'David', 'David', 'Jim', 'Jim') g.last =c('Joyce', 'Einstein', 'Hertz', 'Bailey', 'Compton', 'Jones', 'Wilson', 'Smith', 'Anderson' ) c2 = paste(g.last, g.first, sep=', ') K = GetStudentNames(c2)
Grade each row of a matrix which is a record of the scanned anwers from a test.
gradeSCAN(j, key)
gradeSCAN(j, key)
j |
matrix, scanned answers from the grading center |
key |
vector, key for grading |
Program sums correct answers and returns the score for each row.
vector of scores
Jonathan M. Lees<[email protected]>
Match ID and Email file
IDandEM(scrfn, sisroster, sel = 1:2, hnote = "Exam Results", SEND = TRUE)
IDandEM(scrfn, sisroster, sel = 1:2, hnote = "Exam Results", SEND = TRUE)
scrfn |
list(ID=number, nam="name on scantron") |
sisroster |
list(ID=number, lastname='last name of student', fullname='full name of student') |
sel |
numeric, index= specify for a specific student |
hnote |
text, subject line on E-mail |
SEND |
logical, if FALSE, do not send |
A set of files has been separated and stored. Each file is to sent to a different student with the exam results.
Side Effects
The IDs of the reference data base (the roster) must match the IDs in the list of files. If not, use repair.id to fix the scantron IDs
Jonathan M. Lees<[email protected]>
repair.id
## Not run: ## read in the names of the files zfile = scan(file="ALLIDS", list(name="", ID=0, tfile=""), sep="," ) ## read in a roster. The roster has ## email addresses that are attached tot he files ## by matching the ID in the zfile with the IDs in the data base load(file="/home/lees/Class/GEOL_105/Grades_2008/EXAM1/BB1.RDATA") jroster = BB1 IDandEM(zfile, jroster, sel=1:10, hnote="GEOL105 EXAM3 Results", SEND=FALSE ) IDandEM(zfile, jroster, hnote="GEOL105 EXAM3 Results", SEND=FALSE ) ######## actual sending IDandEM(zfile, jroster, hnote="GEOL105 EXAM3 Results", SEND=TRUE ) ## End(Not run)
## Not run: ## read in the names of the files zfile = scan(file="ALLIDS", list(name="", ID=0, tfile=""), sep="," ) ## read in a roster. The roster has ## email addresses that are attached tot he files ## by matching the ID in the zfile with the IDs in the data base load(file="/home/lees/Class/GEOL_105/Grades_2008/EXAM1/BB1.RDATA") jroster = BB1 IDandEM(zfile, jroster, sel=1:10, hnote="GEOL105 EXAM3 Results", SEND=FALSE ) IDandEM(zfile, jroster, hnote="GEOL105 EXAM3 Results", SEND=FALSE ) ######## actual sending IDandEM(zfile, jroster, hnote="GEOL105 EXAM3 Results", SEND=TRUE ) ## End(Not run)
Given a vector of grades, add the letters to an existing histogram.
jist(h, Z=1, L=1, col=2)
jist(h, Z=1, L=1, col=2)
h |
histogram list |
Z |
grades from original data |
L |
letters associated with grades |
col |
color for plotting letters |
This will add information on an existing histogram plot. If h is the output of do.grades() then Z and L are ignored.
Graphical Side effects
Jonathan M. Lees<[email protected]>
do.grades
g = rnorm(130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ####G1 = do.grades(g, cut=20, tit="GEOL 105 Exam 1") ########## replot with existing divisions: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") jist(D1$hist, D1$grades, D1$lett) ########## or simply: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") jist(D1)
g = rnorm(130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) ####G1 = do.grades(g, cut=20, tit="GEOL 105 Exam 1") ########## replot with existing divisions: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") jist(D1$hist, D1$grades, D1$lett) ########## or simply: D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") jist(D1)
given a numeric grade return a letter grade
LETGRADE(g)
LETGRADE(g)
g |
numeric grade between 1-100 |
returns a grade based on a 4 point spread
character vector of grades
Failing grade is "E" by default. There is no "A+" in this program (UNC policy)
Jonathan M. Lees<[email protected]>
g = rnorm(25, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 L = LETGRADE(g) cbind(g, L)
g = rnorm(25, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 L = LETGRADE(g) cbind(g, L)
Given a question bank, create a test.
make.exam(Qbank, ofile = "examq.tex", ncol=2)
make.exam(Qbank, ofile = "examq.tex", ncol=2)
Qbank |
Question bank list |
ofile |
Output file |
ncol |
number of columns on page, default=2 |
Dumps out a tex file with the questions
Side Effects - output to a TEX file.
Jonathan M. Lees<[email protected]>
prep.exam
data(QBANK1) ## Not run: make.exam(QBANK1, ofile="exam1.tex") ## End(Not run)
data(QBANK1) ## Not run: make.exam(QBANK1, ofile="exam1.tex") ## End(Not run)
Create Solution File in Latex
make.solution(Qbank, ofile = "answers.tex")
make.solution(Qbank, ofile = "answers.tex")
Qbank |
Question Bank |
ofile |
Output File |
Creates a latex file suitable for printing solution to the exam.
Side Effects
Jonathan M. Lees<[email protected]>
data(QBANK1) ## Not run: make.solution(QBANK1, ofile= "solutions.tex") ## End(Not run)
data(QBANK1) ## Not run: make.solution(QBANK1, ofile= "solutions.tex") ## End(Not run)
Plot Histogram with Grades labeled
phist(G, Z = 1, L = 1, col = 2, add = FALSE, tit = "GEOL 105 Exam 1")
phist(G, Z = 1, L = 1, col = 2, add = FALSE, tit = "GEOL 105 Exam 1")
G |
Histogram list from do.grades |
Z |
numerical grades |
L |
text, vector, Letter Grades |
col |
color for text |
add |
logical, add=TRUE, add to existing plot |
tit |
title for plot |
List:
x |
x location on plot |
y |
y location on plot |
L |
Label printed |
Jonathan M. Lees<[email protected]>
do.grades
## Not run: newID3 = repair.id(DBB, raw3) raw3$id=newID3 raw3$ID=newID3 ## End(Not run)
## Not run: newID3 = repair.id(DBB, raw3) raw3$id=newID3 raw3$ID=newID3 ## End(Not run)
Prepare Exam for Latex - use simple styles
prep.exam(OF, incfile, instructor="", examdate="", course="", examname="", instructions="", ncol=2)
prep.exam(OF, incfile, instructor="", examdate="", course="", examname="", instructions="", ncol=2)
OF |
Character string output files |
incfile |
Character, include file name for questions |
instructor |
name of instructor |
examdate |
Date of the examination |
course |
Name of the course, character |
examname |
title of exam |
instructions |
character vector of instructions |
ncol |
number of columns on page, default=2 |
Side Effects
Jonathan M. Lees<[email protected]>
version.exam
## Not run: ###### since the program produces a file on the local ###### system, do not run this example examdate="THURS Sep 20 2007" seqnum="1" exnumber="Exam 1" V = "exam1A" outtex = paste(sep=".",V, "tex" ) outMAST = paste(sep="", V, "MAST" ) MASTtex = paste(sep=".", outMAST , "tex" ) outsolut = paste(sep="", V, "solutions.tex" ) Me = "Jonathan M. Lees" course="GEOL 105" examname=paste(sep=" ", exnumber, "Seq", seqnum) instructions=c("There are 50 questions.", "Answer all questions.", "Mark clearly.") \dontrun{ prep.exam(outMAST, outtex , instructor=Me, examdate=examdate, course=course, examname=examname, instructions=instructions) } ## End(Not run)
## Not run: ###### since the program produces a file on the local ###### system, do not run this example examdate="THURS Sep 20 2007" seqnum="1" exnumber="Exam 1" V = "exam1A" outtex = paste(sep=".",V, "tex" ) outMAST = paste(sep="", V, "MAST" ) MASTtex = paste(sep=".", outMAST , "tex" ) outsolut = paste(sep="", V, "solutions.tex" ) Me = "Jonathan M. Lees" course="GEOL 105" examname=paste(sep=" ", exnumber, "Seq", seqnum) instructions=c("There are 50 questions.", "Answer all questions.", "Mark clearly.") \dontrun{ prep.exam(outMAST, outtex , instructor=Me, examdate=examdate, course=course, examname=examname, instructions=instructions) } ## End(Not run)
Prepare Latex Solution Files
prep.solution(ofile)
prep.solution(ofile)
ofile |
output file name |
Prepares the Latex header for the solution files
Side Effects
Jonathan M. Lees<[email protected]>
prep.exam
## Not run: prep.solution("solfile") ## End(Not run)
## Not run: prep.solution("solfile") ## End(Not run)
Print results from scantron center
printSCANTRON(B1)
printSCANTRON(B1)
B1 |
list, output of readSCANTRON: must have elements studans, Nams, ids |
side effects
Prints the matrix returned from the scantron center.
Jonathan M. Lees<[email protected]>
readSCANTRON
## Not run: datadir = "./DATA" rawfn1 = paste(datadir,'t6200a.raw.csv', sep="/") B1 = readSCANTRON(rawfn1) printSCANTRON(B1) ## End(Not run)
## Not run: datadir = "./DATA" rawfn1 = paste(datadir,'t6200a.raw.csv', sep="/") B1 = readSCANTRON(rawfn1) printSCANTRON(B1) ## End(Not run)
Example Question Bank, 50 question, multiple Choice
data(QBANK1)
data(QBANK1)
List:
Question in latex format (character string)
Possible Answers in latex format (vector of character strings)
Correct Answer in latex format (character string)
index number corresponding to correct answer
character: full path to figure, tag for figure
An example input question in ascii format is constructed using three tag identifiers: "QUESTION:", "ANSWER:" and (optionally) "FIG:". The format is shown here:
data(QBANK1) ## maybe str(QBANK1) ; plot(QBANK1) ... print(QBANK1[[1]])
data(QBANK1) ## maybe str(QBANK1) ; plot(QBANK1) ... print(QBANK1[[1]])
Randomly re-order the questions in a Question Bank
ran.exam(Qbank)
ran.exam(Qbank)
Qbank |
Question Bank List |
randomly re-order the questions in a Question Bank
Question bank
Jonathan M. Lees<[email protected]>
Get.testbank
data(QBANK1) NEWQB = ran.exam(QBANK1)
data(QBANK1) NEWQB = ran.exam(QBANK1)
Read UNC scantron
readSCANTRON(fn = "t9543b.raw.csv", nq = 50, istart = 6)
readSCANTRON(fn = "t9543b.raw.csv", nq = 50, istart = 6)
fn |
character, name of digital file with raw scores |
nq |
integer, Number of questions to read |
istart |
integer, start of column for first question |
The data is scanned by machine. If a student marks on the exam past the correct number of questions, the machine assumes there are legitimate repsonses beyond the key.
list:
Nstudents |
number of students |
Nquestions |
number of questions |
Nams |
names of students |
ids |
Ids of students |
studans |
matrix, student answers |
key |
key for grading |
Jonathan M. Lees<[email protected]>
## Not run: datadir = "./DATA" rawfn1 = paste(datadir,'t6200a.raw.csv', sep="/") B1 = readSCANTRON(rawfn1) ## End(Not run)
## Not run: datadir = "./DATA" rawfn1 = paste(datadir,'t6200a.raw.csv', sep="/") B1 = readSCANTRON(rawfn1) ## End(Not run)
Rename the answers on a Question Bank
rename.answers(Qbank, newnames = letters[1:26], sep = ") ")
rename.answers(Qbank, newnames = letters[1:26], sep = ") ")
Qbank |
Question Bank |
newnames |
vector of new names |
sep |
separator between name of Answer and Answer String |
Takes the given list of questions, and returns same list with answers rpefaces by a different set of itemizers
Question Bank List
Jonathan M. Lees<[email protected]>
Get.testbank
data(QBANK1) newnames=letters[1:26] NEWQB = rename.answers(QBANK1, newnames=newnames ) NEWQB[[35]] newnames=1:26 NEWQB = rename.answers(QBANK1, newnames=newnames ) NEWQB[[35]] newnames=LETTERS[1:26] NEWQB = rename.answers(QBANK1, newnames=newnames ) NEWQB[[35]]
data(QBANK1) newnames=letters[1:26] NEWQB = rename.answers(QBANK1, newnames=newnames ) NEWQB[[35]] newnames=1:26 NEWQB = rename.answers(QBANK1, newnames=newnames ) NEWQB[[35]] newnames=LETTERS[1:26] NEWQB = rename.answers(QBANK1, newnames=newnames ) NEWQB[[35]]
Repair Poorly Bubbled Student IDs by matching to a reliable data base of names and IDs. Routine offers a set of possible matches if several may be appropriate.
repair.id(sisroster, scrfn)
repair.id(sisroster, scrfn)
sisroster |
Reference Data set |
scrfn |
Scantron Output |
Program searchers for missing ID's by attempting to match up names.
newid |
New vector of IDs that correspond to the scantron input |
Jonathan M. Lees<[email protected]>
Replace NA with somehting else
ridNA(z, temp)
ridNA(z, temp)
z |
vector |
temp |
replacement |
vector with NA's replaces
Jonathan M. Lees<[email protected]>
z = 1:10 z[z>8] = NA ridNA(z, 0)
z = 1:10 z[z>8] = NA ridNA(z, 0)
Randomly rearrange answers within a question of a test bank
scramble.answers(Qbank)
scramble.answers(Qbank)
Qbank |
Question Bank (list of Questions) |
Takes the given list of questions, and returns same list with answers scrambled.
Question Bank List
Since some question require that the answers be ordered in a certain way, these are not Randomized in this scrambling process. These include:
c("all of the above",
"none of the above",
"None of these are correct",
"all of the choices are correct",
"All of the choices are correct",
"Both choices are correct",
"None of the choices are correct",
"Both of the choices are correct",
"All of these are correct",
'Neither of these are correct')
Jonathan M. Lees<[email protected]>
Get.testbank
data(QBANK1) QBANK1[[35]] NEWQB = scramble.answers(QBANK1) NEWQB[[35]]
data(QBANK1) QBANK1[[35]] NEWQB = scramble.answers(QBANK1) NEWQB[[35]]
Search a question bank for key words.
SEARCHbank(gw, y = "humidity")
SEARCHbank(gw, y = "humidity")
gw |
Question Bank |
y |
key word |
Dumps to the screen the questions that match the key.
Side effects - dumps to the screen. returns a vector of questions that match.
Jonathan M. Lees<[email protected]>
seebank,Get.testbank,SELbank,COMPbank
## Not run: #### seebank program is interactive - data(QBANK1) SEARCHbank(QBANK1, "humidity" ) ## End(Not run)
## Not run: #### seebank program is interactive - data(QBANK1) SEARCHbank(QBANK1, "humidity" ) ## End(Not run)
Prints out a bank of questions, one at a time
seebank(QB)
seebank(QB)
QB |
QuestionBank Structure |
Side effects
Jonathan M. Lees<[email protected]>
## Not run: #### seebank program is interactive - data(QBANK1) seebank(QBANK1) ## End(Not run)
## Not run: #### seebank program is interactive - data(QBANK1) seebank(QBANK1) ## End(Not run)
Print questions to the screen
seequestions(QB)
seequestions(QB)
QB |
Question Bank |
Prints just the questions to the screen.
Prints to screen
Jonathan M. Lees<[email protected]>
seebank
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF cbind( seequestions(kbank[[1]]) ) ## End(Not run)
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF cbind( seequestions(kbank[[1]]) ) ## End(Not run)
Select, random set of questions from a test bank.
SELbank(QB, N, xclude=NULL)
SELbank(QB, N, xclude=NULL)
QB |
Question bank |
N |
integer, number of questions to select |
xclude |
integer vector, index of questions to exclude, default=NULL |
Progam uses sample to get a random perturbation, and then pulls out the first N questions
Question bank
Jonathan M. Lees<[email protected]>
Get.testbank
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF Kbank = vector(mode='list') for(i in 1:length(kbank)) { Kbank = c(Kbank, kbank[[i]]) } ########## get 50 sample questions NEWQB = SELbank(Kbank, 50) ## End(Not run)
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF Kbank = vector(mode='list') for(i in 1:length(kbank)) { Kbank = c(Kbank, kbank[[i]]) } ########## get 50 sample questions NEWQB = SELbank(Kbank, 50) ## End(Not run)
Show Distribution of Grades
show.dist(W)
show.dist(W)
W |
list output of do.grades |
Print out the distribution of letter grades
Side Effects
Jonathan M. Lees<[email protected]>
do.grades
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") show.dist(D1)
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") show.dist(D1)
Extract a subset from a question bank
subsetbank(QBANK, sel)
subsetbank(QBANK, sel)
QBANK |
Question Bank List |
sel |
integer vector of index to specific questions |
for selecting specific questions
Question Bank with selections
Jonathan M. Lees<[email protected]>
SELbank, COMPbank
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF Kbank = vector(mode='list') for(i in 1:length(kbank)) { Kbank = c(Kbank, kbank[[i]]) } ########## get 50 odd numbered sample questions isel = seq(from=1, to=100, by=2) oddset1 = subsetbank(Kbank, isel) ## End(Not run)
## Not run: LF = list.files(path="/home/lees/Class/GEOL_105/TESTBANK/EXAM_1", pattern="txt", full.names=TRUE ) kbank = vector(mode='list') ###### read in the question banks, each in one file for(i in 1:length(LF)) { h = Get.testbank(LF[i]) kbank[[i]] = Get.testbank(LF[i]) } names(kbank) = LF Kbank = vector(mode='list') for(i in 1:length(kbank)) { Kbank = c(Kbank, kbank[[i]]) } ########## get 50 odd numbered sample questions isel = seq(from=1, to=100, by=2) oddset1 = subsetbank(Kbank, isel) ## End(Not run)
Create a KEY for the scantron
UNCkeytron(g, fout, LAB = "KEY")
UNCkeytron(g, fout, LAB = "KEY")
g |
vector of correct answers |
fout |
output file name |
LAB |
Label to print on key |
Given a vector of correct answers the program will create a postscript file with a facsimile of the scantron used for examinations at UNC Chapel Hill. The Bubbles will be filled and can be used to prepare a number 2 pencil version.
Side effects
Currently only eps outputs - future versions may be different.
At this time, the code creates postscript code, which can be converted
to png, pdf or other formats with software outside of R.
In linux I use a perlscript,
/home/lees/Progs/Perl/ps2png.prl files.eps
which, in turn, calls, epstopdf
and
gs -dBATCH -sDEVICE=png16m -dNOPAUSE -r200 -sOutputFile=$outpf $inpf
Jonathan M. Lees<[email protected]>
getKEY
## Not run: fkeyA = "/Users/lees/SCANTRON/A.FINAL.key" fkeyB = "/Users/lees/SCANTRON/B.FINAL.key" FKEY1 = getKEY(fkeyA) FKEY2 = getKEY(fkeyB) UNCkeytron(FKEY1, "AKEYfinal.eps", "A KEY final") UNCkeytron(FKEY2, "BKEYfinal.eps", "B KEY final") ## End(Not run)
## Not run: fkeyA = "/Users/lees/SCANTRON/A.FINAL.key" fkeyB = "/Users/lees/SCANTRON/B.FINAL.key" FKEY1 = getKEY(fkeyA) FKEY2 = getKEY(fkeyB) UNCkeytron(FKEY1, "AKEYfinal.eps", "A KEY final") UNCkeytron(FKEY2, "BKEYfinal.eps", "B KEY final") ## End(Not run)
Create 1 instance of a specific Exam
version.exam(Qbank, V, exnumber = "Exam 1", seqnum = "2", examdate ='', instructor="", course="", instructions="", SAMP=TRUE, ncol=2)
version.exam(Qbank, V, exnumber = "Exam 1", seqnum = "2", examdate ='', instructor="", course="", instructions="", SAMP=TRUE, ncol=2)
Qbank |
question bank |
V |
Character string output files |
exnumber |
Exam number |
seqnum |
Version Number |
examdate |
Date of the examination |
instructor |
character, name of teacher |
course |
character, nqme of course |
instructions |
vector of character strings |
SAMP |
logical, if TRUE a random ordering to the questions is produced |
ncol |
number of columns on page, default=2 |
Side Effects
Jonathan M. Lees<[email protected]>
ran.exam, make.exam, prep.exam
## the example creates files on the local system - thus not run ## Not run: data(QBANK1) examdate="THURS Sep 20 2007" version.exam(QBANK1, "exam1A" , exnumber="Exam 1", seqnum="1", examdate=examdate) ################## examdate=date() seqnum="1" exnumber="Exam 1" V = "exam1A" outtex = paste(sep=".",V, "tex" ) outMAST = paste(sep="", V, "MAST" ) MASTtex = paste(sep=".", outMAST , "tex" ) outsolut = paste(sep="", V, "solutions.tex" ) Me = "Jonathan M. Lees" course="GEOL 105" examname=paste(sep=" ", exnumber, "Seq", seqnum) K = length(QBANK1) instructions=c( paste(sep=" ", "There are",K," number of questions."), "Answer all questions.","Use number 2 pencil", "Mark each box clearly.") version.exam(QBANK1, "exam1B" , exnumber="Exam 1", seqnum="B", examdate=examdate, instructor=Me, course=course , instructions=instructions) ## End(Not run)
## the example creates files on the local system - thus not run ## Not run: data(QBANK1) examdate="THURS Sep 20 2007" version.exam(QBANK1, "exam1A" , exnumber="Exam 1", seqnum="1", examdate=examdate) ################## examdate=date() seqnum="1" exnumber="Exam 1" V = "exam1A" outtex = paste(sep=".",V, "tex" ) outMAST = paste(sep="", V, "MAST" ) MASTtex = paste(sep=".", outMAST , "tex" ) outsolut = paste(sep="", V, "solutions.tex" ) Me = "Jonathan M. Lees" course="GEOL 105" examname=paste(sep=" ", exnumber, "Seq", seqnum) K = length(QBANK1) instructions=c( paste(sep=" ", "There are",K," number of questions."), "Answer all questions.","Use number 2 pencil", "Mark each box clearly.") version.exam(QBANK1, "exam1B" , exnumber="Exam 1", seqnum="B", examdate=examdate, instructor=Me, course=course , instructions=instructions) ## End(Not run)
Write grades on Histogram
wrist(DB)
wrist(DB)
DB |
Output of do.grades |
Used internally in plotting programs
Side Effects
Jonathan M. Lees<[email protected]>
do.grades
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") hist(g) wrist(D1)
g = rnorm(n=130, m=82, sd=10) g[g>100] = 100 g[g<1] = 1 B = boxplot(g) divs = c(min(g), B$stats[1:4] + diff(B$stats)/2, max(g) ) D1 = do.grades(g, divs=divs, tit="GEOL 105 Exam 1") hist(g) wrist(D1)