When I try to generate the exams' solution with the exams2nops(...template="solution"...) I get the following error message:
Error in exams2pdf(file, n = n, nsamp = nsamp, dir = dir, name = name, :
formal argument "template" matched by multiple actual arguments
How can I produce an exams' solution with the exams2nops?
You cannot do that in one go, you need two runs after setting the same seed, e.g.,
set.seed(1)
exams2nops(my_exam)
set.seed(1)
exams2pdf(my_exam, template = "my_solution.tex")
You can use the solution.tex provided within the package as a starting point for my_solution.tex. But you may want to translate it to your natural language, use the name of your university, possibly insert a logo, add your actual exam name, possibly some into text etc. In exams2pdf() you need to add these things in the template LaTeX file directly.
won't the template="solution" not work in the exams2pdf? Also, can we do something like:
usepackage = "pdfpages", intro = intro2,... ?
Related
I am using exams2pdf() to generate two PDF files as:
exams2pdf(file = "ICvar.Rmd",
name = "icvar",
engine = "knitr",
verbose = FALSE,
texdir = "tmptex",
template = c("exam", "solution")
)
But I get this error:
Error in base::file(out_tex[j], open = "w+", encoding = encoding) : invalid 'description' argument
Any ideas why?
Also, is it possible to use custom templates in exams2nops() like template = c("exam", "solution") to produce two PDF files, the first with the questions; the second with the solutions? I read the vignette but could not find any information and adding template to options in exams2nops() does nothing.
The problem is that you only provide a single name = "icvar" but actually need two distinct names for template = "exam" and template = "solution", respectively. Hence, lacking a second name lead to the somewhat cryptic error message. A simple solution is to provide a vector of two name = c("icex", "icsol"), say.
Additionally, I have just committed a fix to the development version on R-Forge that points this out more clearly in ?exams2pdf, throws an intelligible warning, and provides a workaround. If you use your code above, name is changed to name = c("icvar_exam", "icvar_solution") automatically.
As for exams2nops(): Internally this essentially sets up a standardized template via make_nops_template() and then calls exams2pdf(). No additional templates can be provided. The reason for this is that all the convenient options in the NOPS template (e.g., adding an intro, selecting the language, switching to twocolumn layout, etc.) would only work for the NOPS template but not the other templates provided. Therefore, if you want to produce a solution sheet you have to use another call to exams2pdf() (or exams2html() or exams2pandoc()) after setting the same random seeds as for exams2nops().
I have a LaTeX template, which I use with exam2pdf and where I would like to have the date of the exam as a parameter, whose value should be passed from R. Is that possible?
Yes, you can do this in two and a half ways:
(1) Via the header argument
You can set exams2pdf(..., header = ..., template = ...) where the content of the header is inserted into the template by replacing the %% \exinput{header} placeholder. Thus, when writing the template you can decide where exactly the header code ends up in the LaTeX code and you can make sure that the appropriate commands/packages are available. The header can then be specified in the following ways:
LaTeX code:
You can include something like header = "\\command{value}". There could be more complex pieces of LaTeX code, involving multiple lines, etc.
List of commands and values:
Instead of the full LaTeX code it might be more R-like to use a list specification like header = list(command = "value"). This is transformed internally to the LaTeX code mentioned above.
List of functions:
Finally you can also have a specification like header = list(command = valuefun) where valuefun is a function(i) so that you return a different string for the i-th random version of the exam.
List of all of the above:
A list consisting of unnamed character strings, named character string, and named functions can be used as well, combining all three specifications above.
More details are provided in the vignette("exams", package = "exams") which explains the design of exams2pdf() and how it can be leveraged. It also includes some examples which you can also copy to your working directory via exams_skeleton(write = "exams2pdf", ...). You can look at the exam.tex LaTeX template that is shipped with the package to see how you can insert a date and an ID (depending on the i-th iteration) into the PDF. For example:
exams2pdf("capitals.Rmd", template = "exam.tex",
header = list(Date = "2022-02-22", ID = function(i) paste("\\#", i)))
(2) Write a template generator
For the purposes from your question strategy (1) should be sufficient, I guess. However, if you need more control over what is done in the LaTeX template, then my recommendation would be to write a dynamic template generator. This is how exams2nops() is set up. It takes a lot of arguments that can be set by the user and then proceeds as follows:
Depending on the user arguments a corresponding nops.tex template is written in a temporary directory.
Then exams2pdf(..., template = "/path/to/nops.tex") is called to use this custom temporary template.
Some details, especially the counter for the i-th ID is still handled through the header argument.
I'm creating a small R package that will allow a user to create exams with R code for tables and figures, multiple question types, randomly ordered questions, and randomly ordered responses on multiple choice items. Inserting R code into LaTeX is not problematic, but one issue I've run into is the need to "slap" together text ingested via R with LaTeX commands. Consider this example:
I have this in a LaTeX file:
\newcommand{\question}[1]{
\begin{minipage}{\linewidth}
\item
{#1}
\end{minipage}
}
I read the content with readr::read_file and store it in a variable. I then have the contents of the questions in a .json file:
...
{
"type" : "mc",
"section_no" : 1,
"points" : 2,
"question" : "What is the best beer?",
"correct_answer" : "Hamm's",
"lure_1" : "Miller Lite",
"lure_2" : "PBR",
"lure_3" : "Naturdays",
"lure_4" : "Leine's"
},
...
which I read with jsonlite::fromJSON (which converts to a dataframe), do some massaging, and store in a variable. Let's call the questions and their available options questions. What I've been doing is putting the necessary LaTeX content together with the character string manually with
question.tex <- paste0("\\question{", question[i], "\\\\")
to achieve this in the knitted .tex file:
\question{What is the best beer?\\A. PBR\\B. Naturdays\\C. Miller Lite\\D. Leine's\\E. Hamm's\\}
but I'm thinking there has to be a better way to do this. I'm looking for a function that will allow for a more seamless passing of arguments to my LaTeX command, something like knitr::magic_func(latex.command, question[i]) to achieve the result above. Does this exist?
Maybe I am asking for an extra level of abstraction that knitr doesn't have (or wasn't designed to have)? Or perhaps there's a better way? I guess at this point I'm not far away from being able to create a function that reads the LaTeX command name, number of arguments, and inserts text appropriately, but better to not reinvent the wheel! Also, I think this question could be generalized to simpler commands like \title, \documentclass, etc.
Small MWE:
## (more backslashes since we need to escape in R)
tex.command <- "\\newcommand{\\question}[1]{
\\begin{minipage}{\\linewidth}
\\item
{#1}
\\end{minipage}
}"
q <- "What is the best beer?\\\\A. PBR\\\\B. Naturdays\\\\C. Miller Lite\\\\D. Leine's\\\\E. Hamm's\\\\"
## some magic function here?
magic_func(tex.command, q)
## desired result
"\\question{What is the best beer?\\\\A. PBR\\\\B. Naturdays\\\\C. Miller Lite\\\\D. Leine's\\\\E. Hamm's\\\\\\\\"
I'm working on a document in R, with knitr to pdflatex and am using the extended version of toLatex from memisc.
When I'm producing a table with cut intervals however, the square brackets are not sanitised and the pdflatex job errors because of the existence of [.
I tried putting sanitize=TRUE in the knitr chunk code, but this only works for tikz.
Previously, I have used gsub and replaced the string in the R object itself which is rather inelegant. I'm hoping someone could point me in the direction of a nuance of memisc or knitr that I'm missing or another function/method that would easily handle latex special characters.
Example
library("memisc")
library("Hmisc")
example<-data.frame(cbind(x=1:100,y=1:100))
example$x<-cut2(example$x,m=20)
toLatex(example)
UPDATE
Searching SO I found a post about applying latexTranslate with apply function, but this requires characters so I would have to unclass from factor to character.
I found another SO post that identifies the knitr:::escape_latex function however, the chunk then outputs the stuff as markup instead of translating it (using results='asis') or produces an R style table inside a code block (using results='markup'). I tried configuring it as a hook function in my parent document and it had the effect of outputting all the document contents as markup. This is a brand new area for me so I probably implemented it incorrectly.
<<setup,include=FALSE>>=
hook_inline = knit_hooks$get('inline')
knit_hooks$set(inline = function(x) {
if (is.character(x)) x = knitr:::escape_latex(x)
hook_inline(x)
})
#
...
<<tab-example,echo=FALSE,cache=TRUE,results='asis',sanitize=TRUE,inline=TRUE>>=
library("Hmisc")
library("memisc")
example<-data.frame(cbind(x=1:100,y=1:100))
example$x<-cut2(example$x,m=20)
toLatex(example)
#
According to #yihui this is the wrong way to go
UPDATE 2
I have created a gsub wrapper which will escape percentages etc, however the [ symbol still pushes latex into maths mode and errors.
Courtesy of folks on the tex SE, a [ directly after a line break(\\) is considered an entry into math-mode. It is very simple to prevent this behaviour by adding {} into the output just before a [. My function looks like:
escapedLatex<-function (df = NULL)
{
require("memisc")
gsub(gsub(x = toLatex(df, show.xvar = TRUE), pattern = "%",
replacement = "\\%", fixed = TRUE), pattern = "[", replacement = "{}[",
fixed = TRUE)
}
I'd be very happy to see any alternative, more elegant solutions around and will leave it open for a few days.
I am using tableNominal{reporttools} to produce frequency tables. The way I understand it, tableNominal() produces latex code which has to be copied and pasted onto a text file and then saved as .tex. But is it possible to simple export the table produced as can be done in print(xtable(table), file="path/outfile.tex"))?
You may be able to use either latex or latexTranslate from the "Hmisc" package for this purpose. If you have the necessary program infrastructure the output gets sent to your TeX engine. (You may be able to improve the level of our answers by adding specific examples.)
Looks like that function does not return a character vector, so you need to use a strategy to capture the output from cat(). Using the example in the help page:
capture.output( TN <- tableNominal(vars = vars, weights = weights, group = group,
cap = "Table of nominal variables.", lab = "tab: nominal") ,
file="outfile.tex")