3.10 Value Check (S)

Purpose: Checks whether the values in a column of the student’s tibble match the answer key.

Motivation: Some questions involve the transformation of a column’s values – for example, multiplying a column by a formula. This Check detects an incorrectly transformed (or unaltered) column and can hint at its proper transformation. The sort() function allows for flexible column ordering.

#Value Check Example

else if(!isTRUE(all.equal(variable_name$column_name |> sort(na.last = T), 
                           variable_name_test$column_name |> sort(na.last = T),
                           tolerance = 0.001,
                           check.attributes = F))){
  test.results[2, 4] <- "The values of `column_name` are incorrect. (Any additional feedback as needed.)"
}

Technicals

Since the Value Check assumes that the student’s answer has the correct column name, it is essential that the Column Name Check is placed beforehand.

The Value Check is a general check for a column’s values. For more specialized checks, see the Calculation Check, the NA Check, or the Expression Check.

By default, NA values are removed from a vector when sorted. The na.last = T argument ensures that the NA values are placed last in the sorted vector but not removed.

If it is reasonable to check every column in the tibble (e.g., a very complicated public question with many intermediate steps), you could implement a Complete Value Check, as shown below. Note that loops in R do consume considerable computational resources – there are certainly other and/or better ways to do this, like through the sapply() function.

#Complete Value Check Example
#By construction below, this check should be implemented as the final check (the last `else if` or the `else` statement)

else { 
  q2ccheck <- c()
      #Compares every column in the student's tibble with the corresponding answer key column...
      for (colname in colnames(variable_name)){ 
        if(!isTRUE(all.equal(variable_name[[colname]] |> sort(na.last = T), 
                             variable_name_test[[colname]] |> sort(na.last = T),
                             tolerance = 0.001,
                             check.attributes = F))){
          q2ccheck <- append(q2ccheck, colname)
        }
      }
  
#Returns a list of incorrect columns... 
  test.results[2, 4] <- paste0(c("The following columns are incorrect: ",
                                paste0(q2ccheck, collapse = ", "),
                                "(Any additional feedback as needed.)"), collapse = "")
}

For examples of how to check multiple columns simultaneously, see below.

#Dynamic Value Check Example 

else if(any(!isTRUE(all.equal(variable_name$column_A |> sort(na.last = T), 
                              variable_name_test$column_A |> sort(na.last = T), 
                              tolerance = 0.001, check.attributes = F))), 
            !isTRUE(all.equal(variable_name$column_B |> sort(na.last = T), 
                              variable_name_test$column_B |> sort(na.last = T), 
                              tolerance = 0.001, check.attributes = F))){ 
  
  value_check <- c(!isTRUE(all.equal(variable_name$column_A |> sort(na.last = T), 
                                     variable_name_test$column_A |> sort(na.last = T), 
                                     tolerance = 0.001, check.attributes = F)), 
                   !isTRUE(all.equal(variable_name$column_B |> sort(na.last = T), 
                                     variable_name_test$column_B |> sort(na.last = T),
                                     tolerance = 0.001, check.attributes = F)))
    
  value_names <- c("column_A", "column_B")
   
  test.results[2, 4] <- paste0(c("The following column(s) are incorrect: ", value_names[value_check], ". (Any additional feedback as needed.)"), collapse = " ")
}