I am using num_to_choice
to generate 5 options for a numeric exercise using the r exams
package.
I want my sc$questions
to include the correct solution (res
) plus two calculated wrong solutions (err1
and err2
). I am using this code:
sc <- num_to_schoice(res, digits=3, wrong=c(err1, err2))
I do get the five options generated, one with the correct solution (res
), but none of the other four options include err1
and err2
. Reading the num_to_choice
documentation I find:
"The wrong solutions can be provided or are generated randomly. If wrong is provided only up to 2 elements of it are used in order to assure some random solutions."
However, in my case none of the err1
or err2
options are included in the sc$questions
. What am I missing here? How can I force the err
options to be included in the sc$questions
?
Here is an reproducible example:
v <- c(1225,4000,1372,974,956,940,1532,969,1070,685,220,407,903,239,283,368,483,352,77,699)
res <- sd(v)
err1 <- IQR(v)
err2 <- sqrt(var(v)*(length(v-1)/length(v)))
set.seed(1)
sc <- num_to_schoice(res, digits=3, wrong=c(err1, err2), range=c(0,max(v)))
and here is the solution generated by sc$questions
:
The result is "specified 'wrong' is too small for 'delta'"
In your case err2
and res
are identical:
identical(res, err2)
## [1] TRUE
That is why num_to_schoice()
returns NULL
along with a warning that should inform you that the difference from res
to the wrong
argument is too small for the given delta
. Hence, it is not possible to include res
as the correct solution and err2
as a wrong solution.
The source of the problem is that you compute
length(v - 1)
which is the same as length(v)
rather than the intended
length(v) - 1
If you do
err2 <- sqrt(var(v) * (length(v) - 1)/length(v))
Then you get the desired
set.seed(1)
num_to_schoice(res, digits = 3, wrong = c(err1, err2))
## $solutions
## [1] FALSE FALSE FALSE TRUE FALSE
##
## $questions
## [1] "$819.235$" "$634.000$" "$996.905$" "$840.517$" "$1222.200$"
By design num_to_schoice()
is rather conservative: If it thinks it cannot find a set of items with the desired properties it returns NULL
rather than trying to find an approximate solution. This is to avoid randomly getting exercises that might be simpler than intended.
Another typical example is that the range
is too small and/or the delta
too large to produce a list of five answer options that conform with all arguments. For example, let's assume we have the following correct solution and two distractors:
res <- 1.234
err1 <- 2.345
err2 <- 3.456
Then, the command you posted above will not work:
num_to_schoice(res, digits = 3, wrong = c(err1, err2))
## NULL
## Warning message:
## In num_to_schoice(res, digits = 3, wrong = c(err1, err2)) :
## specified 'range' is too small for 'delta'
The reason is that the default delta
is 1 and the default range
is c(0.5, 1.5) * res
in this case. And this is not large enough to accomodate five answers with a minimum delta
of 1.
But if you increase the range
(or alternatively decrease the delta
) you get:
set.seed(1)
num_to_schoice(res, digits = 3, wrong = c(err1, err2), range = c(0, 10))
## $solutions
## [1] FALSE FALSE FALSE TRUE FALSE
##
## $questions
## [1] "$3.456$" "$2.345$" "$4.496$" "$1.234$" "$9.195$"
where res
ends up in position 4 while err1
and err2
are in positions 2 and 1, respectively.