The following function accepts a vector, and returns the modal (most common) value.
modal_value <- function(x)
{
names(sort(table(x), decreasing = TRUE)[1])
}
Write some unit tests for this function.
Since the function always returns a character vector, (it uses names
), the expected value should be a character vector too.
test_that(
"modal_value, with a single most common value, returns that value",
{
x <- rep(1:5, times = c(1, 2, 3, 2, 1))
expected <- "3"
actual <- modal_value(x)
expect_equal(actual, expected)
}
)
Where the input is bimodal (having two most common values), we need to decide on the best behaviour. Returning both (or all) of them gives more information to the user, but makes the output variable length. this function returns only the first one, and the test reflects that.
test_that(
"modal_value, with two most common values, returns the first most common value",
{
x <- rep(1:5, times = c(1, 3, 2, 3, 1))
expected <- "2" # not c("2", "4")
actual <- modal_value(x)
expect_equal(actual, expected)
}
)
When does the function give a sensible answer, and when does it fail? Write some tests to make sure it fails correctly.
# tests for correct failing
test_that(
"modal_value, with a missing input, throws an error",
{
expect_error(
modal_value(),
'argument "x" is missing, with no default'
)
}
)
Try to improve upon the function to make it easier to test.
Returning a value of the same type as the input would be useful.
# modify this function
modal_value2 <- function(x)
{
class_x <- class(x)
value <- names(sort(table(x), decreasing = TRUE)[1])
as(value, class_x)
}
# tests for the updated function here
test_that(
"modal_value2, with a single most common value, returns that value",
{
x <- rep(1:5, times = c(1, 2, 3, 2, 1))
expected <- 3
actual <- modal_value2(x)
expect_equal(actual, expected)
}
)