How to distribute questions across sections in a LaTeX template? - r-exams

The exam I am planning to write has several sections. Is it possible to distribute the questions by the respective sections while using a LaTeX template?

Yes, but then you need to hard-code the number of questions. Other than that it is very straightforward. Rather than putting a single placeholder into the LaTeX template:
%% \exinput{exercises}
you need to input the exact exercise files, e.g.,
\section{Quiz questions}
\begin{enumerate}
\input{exercise1.tex}
\input{exercise2.tex}
\end{enumerate}
\section{Practical exercises}
\begin{enumerate}
\input{exercise3.tex}
\input{exercise4.tex}
\end{enumerate}
This gives you full control over how and where the exercises are included. More details are given in Section 3 of vignette("exams", package = "exams").
Caveat: Leading zeros are added in the exercise number if there is more than one digit in the number of exercises, e.g., exercise01.tex if there are between ten and 99 exercises.

Related

Extract all text before the last occurrence of a specific word

I wanted to extract all the text before the last occurrence of a specific word:
Please note again that and-approved forms are not to be count toward
the page limit. To the extent possible, please limit the appendix file
to one 50-page PDF submission.
The Project Description must be clear, concise, and complete. is
particularly interested in Project Descriptions that convey strategies
for achieving intended performance. Project Descriptions are evaluated
on the basis of substance and measurable outcomes, not length.
Cross-referencing should be used rather than repetition. Supporting
documents designated as required must be included in the Appendix of
the document
Clearly identify the physical, economic, social, financial,
institutional, and/or other problem(s) requiring a solution. The need
for assistance, including the nature and scope of the problem, must be
demonstrated. Supporting documentation, such as letters of support and
testimonials from concerned parties, may be included in the Appendix.
Any relevant data based on planning studies or needs assessments
should be included or referred to in the endnotes or footnotes.
Incorporate demographic data and participant/beneficiary information,
as available.
Appendix
Any relevant data based on planning studies or needs assessments
should be included or referred to in the endnotes or footnotes.
Incorporate demographic data and participant/beneficiary information,
as available.
And I want to all the text before the last Appendix (excluding Appendix)
currently using this
sub("(.*)Appendix", "", text)
but it only get all the text in the paragraph with the first Appendix. How do I adjust the regex.
Expected output:
Please note again that and-approved forms are not to be count toward
the page limit. To the extent possible, please limit the appendix file
to one 50-page PDF submission.
The Project Description must be clear, concise, and complete. is
particularly interested in Project Descriptions that convey strategies
for achieving intended performance. Project Descriptions are evaluated
on the basis of substance and measurable outcomes, not length.
Cross-referencing should be used rather than repetition. Supporting
documents designated as required must be included in the Appendix of
the document
Clearly identify the physical, economic, social, financial,
institutional, and/or other problem(s) requiring a solution. The need
for assistance, including the nature and scope of the problem, must be
demonstrated. Supporting documentation, such as letters of support and
testimonials from concerned parties, may be included in the Appendix.
Any relevant data based on planning studies or needs assessments
should be included or referred to in the endnotes or footnotes.
Incorporate demographic data and participant/beneficiary information,
as available.
We can find the location of 'Appendix', extract the last (dplyr) 'start'ing index, and get the substring (str_sub) from the start (1) to that location (wrap with trimws to remove any leading/lagging spaces)
library(stringr)
out <- trimws( str_sub(text, 1, dplyr::last(str_locate_all(text,
"Appendix")[[1]][,1])-1))
-output
> cat(out, "\n")
Please note again that and-approved forms are not to be count toward the page limit. To the extent possible, please limit the appendix file to one 50-page PDF submission.
The Project Description must be clear, concise, and complete. is particularly interested in Project Descriptions that convey strategies for achieving intended performance. Project Descriptions are evaluated on the basis of substance and measurable outcomes, not length. Cross-referencing should be used rather than repetition. Supporting documents designated as required must be included in the Appendix of the document
Clearly identify the physical, economic, social, financial, institutional, and/or other problem(s) requiring a solution. The need for assistance, including the nature and scope of the problem, must be demonstrated. Supporting documentation, such as letters of support and testimonials from concerned parties, may be included in the Appendix. Any relevant data based on planning studies or needs assessments should be included or referred to in the endnotes or footnotes. Incorporate demographic data and participant/beneficiary information, as available.
data
text <- "\n\n Please note again that and-approved forms are not to be count toward the page limit. To the extent possible, please limit the appendix file to one 50-page PDF submission.\n\n The Project Description must be clear, concise, and complete. is particularly interested in Project Descriptions that convey strategies for achieving intended performance. Project Descriptions are evaluated on the basis of substance and measurable outcomes, not length. Cross-referencing should be used rather than repetition. Supporting documents designated as required must be included in the Appendix of the document\n\n Clearly identify the physical, economic, social, financial, institutional, and/or other problem(s) requiring a solution. The need for assistance, including the nature and scope of the problem, must be demonstrated. Supporting documentation, such as letters of support and testimonials from concerned parties, may be included in the Appendix. Any relevant data based on planning studies or needs assessments should be included or referred to in the endnotes or footnotes. Incorporate demographic data and participant/beneficiary information, as available.\n\n Appendix\n\n Any relevant data based on planning studies or needs assessments should be included or referred to in the endnotes or footnotes. Incorporate demographic data and participant/beneficiary information, as available.\n"
You can use the following code to select everything before the last occurence of appendix:
sub('-[^Appendix]*$', '', text)
Output:
[1] "Please note again that and-approved forms are not to be count toward the page limit. To the extent possible, please limit the appendix file to one 50-page PDF submission.\n\nThe Project Description must be clear, concise, and complete. is particularly interested in Project Descriptions that convey strategies for achieving intended performance. Project Descriptions are evaluated on the basis of substance and measurable outcomes, not length. Cross-referencing should be used rather than repetition. Supporting documents designated as required must be included in the Appendix of the document\n\nClearly identify the physical, economic, social, financial, institutional, and/or other problem(s) requiring a solution. The need for assistance, including the nature and scope of the problem, must be demonstrated. Supporting documentation, such as letters of support and testimonials from concerned parties, may be included in the Appendix. Any relevant data based on planning studies or needs assessments should be included or referred to in the endnotes or footnotes. Incorporate demographic data and participant/beneficiary information, as available.\n\nAppendix\n\nAny relevant data based on planning studies or needs assessments should be included or referred to in the endnotes or footnotes. Incorporate demographic data and participant/beneficiary information, as available."
Here's a generalisable tidyverse solution to your problem. For illustrative purposes let me demonstrate it using a much shorter example string:
Data #1:
text <- "Appendix abc Appendix def Appendix final"
Solution:
(library(tidyverse)
data.frame(text) %>%
# split `text` into separate words:
separate_rows(text, sep = " ") %>%
# count the words depending on whether they contain `Appendix` or `appendix`:
mutate(count_Appendix = cumsum(str_count(text, "(a|A)ppendix"))) %>%
# subset on those words that are not the maximum (i.e., last) `count_Appendix`:
filter(count_Appendix != max(count_Appendix)) %>%
# put the words back together:
summarise(text = str_c(text, collapse = " "))
# A tibble: 1 × 1
text
<chr>
1 Appendix abc appendix def
In most cases, you will have more than one text string. Two adaptations to the above code are required: (i) create a row identifier and (ii) group_by that identifier before you paste the words back into their original format:
data.frame(text) %>%
# create row identifier:
mutate(row = row_number()) %>%
# split `text` into separate words:
separate_rows(text, sep = " ") %>%
# count the words depending on whether they contain `Appendix` or `appendix`:
mutate(count_Appendix = cumsum(str_count(text, "(a|A)ppendix"))) %>%
# subset on those words that are not the maximum (i.e., last) `count_Appendix`:
filter(count_Appendix != max(count_Appendix)) %>%
# for each `row`:
group_by(row) %>%
# put the words back together:
summarise(text = str_c(text, collapse = " "))
# A tibble: 2 × 2
row text
<int> <chr>
1 1 Appendix abc Appendix def Appendix final
2 2 blah blah Appendix abc
Data #2:
text <- c("Appendix abc Appendix def Appendix final",
"blah blah Appendix abc Appendix finalissimo")
EDIT:
See here for regex solutions: Regex to edit text depending on number of occurrence of key word
You can use sub. The first .* is greedy and will take everything until the last match of Appendix.* and can be reinserted with \\1 when placing it between ().
sub("(.*)Appendix.*", "\\1", text)
Output:
[1] "\n\n Please note again that and-approved forms are not to be count toward the page limit. To the extent possible, please limit the appendix file to one 50-page PDF submission.\n\n The Project Description must be clear, concise, and complete. is particularly interested in Project Descriptions that convey strategies for achieving intended performance. Project Descriptions are evaluated on the basis of substance and measurable outcomes, not length. Cross-referencing should be used rather than repetition. Supporting documents designated as required must be included in the Appendix of the document\n\n Clearly identify the physical, economic, social, financial, institutional, and/or other problem(s) requiring a solution. The need for assistance, including the nature and scope of the problem, must be demonstrated. Supporting documentation, such as letters of support and testimonials from concerned parties, may be included in the Appendix. Any relevant data based on planning studies or needs assessments should be included or referred to in the endnotes or footnotes. Incorporate demographic data and participant/beneficiary information, as available.\n\n "

Extract Text from a pdf only English text Canadian Legislation R

I'm trying to extract data from a Canadian Act for a project (in this case, the Food and Drugs Act), and import it into R. I want to break it up into 2 parts. 1st the table of contents (pic 1). Second, the information in the act (pic 2). But I do not want the French part (je suis désolé). I have tried using tabulizer extract_area(), but I don't want to have to select the area by hand 90 times (I'm going to do this for multiple pieces of legislation).
Obviously I don't have a minimal reproducible example coded out... But the pdf is downloadable here: https://laws-lois.justice.gc.ca/eng/acts/F-27/
Option 2 is to write something to pull it out via XML, but I'm a bit less used to working with XML files. Unless it's incredibly annoying to do using either pdftools or tabulizer, I'd prefer the answer using one of those libraries (mostly for learning purposes).
I've seen some similarish questions on stackoverflow, but they're all confusingly written/designed for tables, of which this is not. I am not a quant/data science researcher by training, so an explanation would be super helpful (but not required).
Here's an option that reads in the pdf text and detects language. You're probably going to have to do a lot of text cleanup after reading in the pdf. Assume you don't care about retaining formatting.
library(pdftools)
a = pdf_text('F-27.pdf')
#split text to get sentence chunks, mostly.
b = sapply(a,strsplit,'\r\n')
#do a bunch of other text cleanup, here's an example using the third list element. You can expand this to cover all of b with a loop or list function like sapply.
#Two spaces should hopefully retain most sentence-like fragments, you can get more sophisticated:
d = strsplit(b[[3]], ' ')[[1]]
library(cld3) #language tool to detect french and english
x = sapply(d,detect_language)
#Keep only English
x[x=='en']

How to grade exams/questions manually?

What I'd like to do:
I would like to use r-exams in the following procedure:
Providing electronic exams in pdf format to students (using exams2pdf(..)
Let the students upload excel file with their answers
Grade the answers using (using eval_nops(...))
My Question:
Is calling the function eval_nops() the preferred way to manually grad questions in r-exams?
If not, which way is to be prefered?
What I have tried:
I'm aware of the exam2nops() function, and I know that it gives back an .RDS file where the correct answers are stored. Hence, I basically have what I need. However, I found that procedure to be not very straightforward, as the correct answers are buried rather deeply inside the RDS file.
Overview
You are right that there is no readily available system for administering/grading exams outside of a standard learning management system (LMS) like Moodle or Canvas, etc. R/exams does provide some building blocks for the grading, though, especially exams_eval(). This can be complemented with tools like Google forms etc. Below I start with the "hard facts" regarding exams_eval() even though this is a bit technical. But then I also provide some comments regarding such approaches.
Using exams_eval()
Let us consider a concrete example
eval <- exams_eval(partial = TRUE, negative = FALSE, rule = "false2")
indicating that you want partial credits for multiple-choice exercises but the overall points per item must not become negative. A correctly ticked box yields 1/#correct points and an incorrectly ticked box 1/#false. The only exception is where there is only one false item (which would then cancel all points) then 1/2 is used.
The resulting object eval is a list with the input parameters (partial, negative, rule) and three functions checkanswer(), pointvec(), pointsum(). Imagine that you have the correct answer pattern
cor <- "10100"
The associated points for correctly and incorrectly ticked boxed would be:
eval$pointvec(cor)
## pos neg
## 0.5000000 -0.3333333
Thus, for the following answer pattern you get:
ans <- "11100"
eval$checkanswer(cor, ans)
## [1] 1 -1 1 0 0
eval$pointsum(cor, ans)
## [1] 0.6666667
The latter would still need to be multiplied with the overall points assigned to that exercise. For numeric answers you can only get 100% or 0%:
eval$pointsum(1.23, 1.25, tolerance = 0.05)
## [1] 1
eval$pointsum(1.23, 1.25, tolerance = 0.01)
## [1] 0
Similarly, string answers are either correct or false:
eval$pointsum("foo", "foo")
## [1] 1
eval$pointsum("foo", "bar")
## [1] 0
Exercise metainformation
To obtain the relevant pieces of information for a given exercise, you can access the metainformation from the nested list that all exams2xyz() interfaces return:
x <- exams2xyz(...)
For example, you can then extract the metainfo for the i-th random replication of the j-th exercise as:
x[[i]][[j]]$metainfo
This contains the correct $solution, the $type, and also the $tolerance etc. Sure, this is somewhat long and inconvenient to type interactively but should be easy enough to cycle through programatically. This is what nops_eval() for example does base on the .rds file containing exactly the information in x.
Administering exams without a full LMS
My usual advice here is to try to leverage your university's services (if available, of course). Yes, there can be problems with the bandwidth/stability etc. but you can have all of the same if you're running your own system (been there, done that). Specifically, a discussion of Moodle vs. PDF exams mailed around is available here:
Create fillable PDF form with exams2nops
http://www.R-exams.org/general/distancelearning/#replacing-written-exams
If I were to provide my exams outside of an LMS I would use HTML, though, and not PDF. In HTML it is much easier to embed additional information (data, links, etc.) than in PDF. Also HTML can be viewed on mobile device moch more easily.
For collecting the answers, some R/exams users employ Google forms, see e.g.:
https://R-Forge.R-project.org/forum/forum.php?thread_id=34076&forum_id=4377&group_id=1337. Others have been interested in using learnr or webex for that:
http://www.R-exams.org/general/distancelearning/#going-forward.
Regarding privacy, though, I would be very surprised if any of these are better than using the university's LMS.

How do I insert text before a group of exercises in an exam?

I am very new to R and to R/exams. I've finally figured out basic things like compiling a simple exam with exams2pdf and exams2canvas, and I've figured out how to arrange exercises such that this group of X exercises gets randomized in the exam and others don't.
In my normal written exams, sometimes I have a group of exercises that require some introductory text (e.g,. a brief case study on which the next few questions are based, or a specific set of instructions for the questions that follow).
How do I create this chunk of text using R/exams and Rmd files?
I can't figure out if it's a matter of creating a particular Rmd file and then simply adding that to the list when creating the exam (like a dummy file of sorts that only shows text, but isn't numbered), or if I have to do something with the particular tex template I'm using.
There's a post on R-forge about embedding a plain LaTeX file between exercises that seems to get at what I'm asking, but I'm using Rmd files to create exercises, not Rnw files, and so, frankly, I just don't understand it.
Thank you for any help.
There are two strategies for this:
1. Separate exercise files in the same sequence
Always use the same sequence of exercises, say, ex1.Rmd, ex2.Rmd, ex3.Rmd where ex1.Rmd creates and describes the setting and ex2.Rmd and ex3.Rmd simply re-use the variables created internally by ex1.Rmd. In the exams2xyz() interface you have to assure that all exercises are processed in the same environment, e.g., the global environment:
exams2pdf(c("ex1.Rmd", "ex2.Rmd", "ex3.Rmd"), envir = .GlobalEnv)
For .Rnw exercises this is not necessary because they are always processed in the global environment anyway.
2. Cloze exercises
Instead of separate exercise files, combine all exercises in a single "cloze" exercise ex123.Rmd that combines three sub-items. For a simple exercise with two sub-items, see: http://www.R-exams.org/templates/lm/
Which strategy to use?
For exams2pdf() both strategies work and it is more a matter of taste whether one prefers all exercises together in a single file or split across separate files. However, for other exams2xyz() interfaces only one or none of these strategies work:
exams2pdf(): 1 + 2
exams2html(): 1 + 2
exams2nops(): 1
exams2moodle(): 2
exams2openolat(): 2
exams2blackboard(): -
exams2canvas(): -
Basically, strategy 1 is only guaranteed to work for interfaces that generate separate files for separate exams like exams2pdf(), exams2nops(), etc. However, for interfaces that create pools of exercises for learning management systems like exams2moodle(), exams2canvas(), etc. it typically often cannot be assured that the same random replication is drawn for all three exercises. (Thus, if there are two random replications per exercise, A and B, participants might not get A/A/A or B/B/B but A/B/A.)
Hence, if ex1/2/3 are multiple-choice exercises that you want to print and scan automatically, then you could use exams2nops() in combination with strategy 1. However, strategy 2 would not work because cloze exercises cannot be scanned automatically in exams2nops().
In contrast, if you want to use Moodle, then exams2moodle() could be combined with strategy 2. In contrast, strategy 1 would not work (see above).
As you are interested in Canvas export: In Canvas neither of the two strategies works. It doesn't support cloze exercises. And to the best of my knowledge it is not straightforward to assure that exercises are sampled "in sync".

How to display points per exercise when printing to pdf via `exams2pdf`?

Consider creating exams using the exams package in R.
When using exams2nops there is a parameter showpoints that, when set to TRUE will show the points of each exercise. However, for exams2pdf this parameter is not available.
How to display the points per exercise when using exams2pdf?
(The answer below is adapted from the R/exams forum at https://R-Forge.R-project.org/forum/forum.php?thread_id=33884&forum_id=4377&group_id=1337.)
There is currently no built-in solution to automatically display the number of points in exams2pdf(). The points= argument only stores the number of points in the R object that exams2pdf() creates (as in other exams2xyz() interfaces) but not in the individual PDF files.
Thus, if you want the points to be displayed you need to do it in some way yourself. A simple solution would be to include it in the individual exercises already, possibly depending on the kind of interface used, e.g., something like this for an .Rmd exercise:
pts <- 17
pts_string <- if(match_exams_call() == "exams2pdf") {
sprintf("_(%s points)_", pts)
} else {
""
}
And then at the beginning of the "Question":
Question
========
`r pts_string` And here starts the question text...
Finally in the meta-information
expoints: `r pts`
This always includes the desired points in the meta-information but only displays them in the question when using exams2pdf(...). This is very flexible and can be easily customized further. The only downside is that it doesn't react to the exams2pdf(..., points = ...) argument.
In .Rnw exercises one would have to use \Sexpr{...} instead of r .... Also the pts_string should be something like sprintf("\\emph{(%s points)}", pts).
Finally, a more elaborate solution would be to create a suitable \newcommand in the .tex template you use. If all exercises have the same number of points, this is not hard to do. But if all the different exercises could have different numbers of points, it would need to be more involved.
The main reason for supporting this in exams2nops() but not exams2pdf() is that the former has a rather restrictive format and vocabulary. In the latter case, however, the point is to give users all freedom regarding layout, language, etc. Hence, I didn't see a solution that is simple enough but also flexible enough to cover all use-cases of exams2pdf().

Resources