diff --git a/R/data_rescale.R b/R/data_rescale.R index 526601716..53eff1e09 100644 --- a/R/data_rescale.R +++ b/R/data_rescale.R @@ -15,12 +15,12 @@ #' For example, if a vector range from 5 to 15 and `multiply = 1.1`, the current #' range of 10 will be expanded by the factor of 1.1, giving a new range of #' 11. Thus, the rescaled vector would range from 4.5 to 15.5. -#' @param add If not `NULL`, `to` is ignored and `add` will be used, giving the -#' amount by which the actual range of `x` should be expanded. For example, -#' if a vector range from 5 to 15 and `add = 1`, the current range of 10 will -#' be expanded by 1, giving a new range of 11. Thus, the rescaled vector would -#' range from 4.5 to 15.5, because the lower and upper bounds are each expanded -#' by half of the amount specified in `add`. +#' @param add A vector of length 1 or 2. If not `NULL`, `to` is ignored and `add` +#' will be used, giving the amount by which the minimum and maximum of the +#' actual range of `x` should be expanded. For example, if a vector range from +#' 5 to 15 and `add = 1`, the range will be expanded from 4 to 16. If `add` is +#' of length 2, then the first value is used for the lower bound and the second +#' value for the upper bound. #' @param range Initial (old) range of values. If `NULL`, will take the range of #' the input vector (`range(x)`). #' @param ... Arguments passed to or from other methods. @@ -54,11 +54,10 @@ #' x #' # both will expand the range by 10% #' rescale(x, multiply = 1.1) -#' rescale(x, add = 1) +#' rescale(x, add = 0.5) #' -#' # "expand" range by 50% -#' rescale(x, multiply = 1.5) -#' rescale(x, add = 5) +#' # expand range by different values +#' rescale(x, add = c(1, 3)) #' #' # Specify list of multipliers #' d <- data.frame(x = 5:15, y = 5:15) @@ -317,11 +316,27 @@ rescale.data.frame <- function(x, } # multiply? If yes, calculate the "add" value if (!is.null(multiply)) { - add <- diff(range(x, na.rm = TRUE)) * (multiply - 1) + # check for correct length + if (length(multiply) > 1) { + insight::format_error("The length of `multiply` must be 1.") + } + add <- (diff(range(x, na.rm = TRUE)) * (multiply - 1)) / 2 } # add? if (!is.null(add)) { - to <- c(min(x, na.rm = TRUE) - (add / 2), max(x, na.rm = TRUE) + (add / 2)) + # add must be of length 1 or 2 + if (length(add) > 2) { + insight::format_error("The length of `add` must be 1 or 2.") + } + # if add is of length 2, then the first value is used for the lower bound + # and the second value for the upper bound + if (length(add) == 2) { + add_low <- add[1] + add_high <- add[2] + } else { + add_low <- add_high <- add + } + to <- c(min(x, na.rm = TRUE) - add_low, max(x, na.rm = TRUE) + add_high) } to } diff --git a/man/rescale.Rd b/man/rescale.Rd index eb4f5977e..86469a48e 100644 --- a/man/rescale.Rd +++ b/man/rescale.Rd @@ -51,12 +51,12 @@ For example, if a vector range from 5 to 15 and \code{multiply = 1.1}, the curre range of 10 will be expanded by the factor of 1.1, giving a new range of 11. Thus, the rescaled vector would range from 4.5 to 15.5.} -\item{add}{If not \code{NULL}, \code{to} is ignored and \code{add} will be used, giving the -amount by which the actual range of \code{x} should be expanded. For example, -if a vector range from 5 to 15 and \code{add = 1}, the current range of 10 will -be expanded by 1, giving a new range of 11. Thus, the rescaled vector would -range from 4.5 to 15.5, because the lower and upper bounds are each expanded -by half of the amount specified in \code{add}.} +\item{add}{A vector of length 1 or 2. If not \code{NULL}, \code{to} is ignored and \code{add} +will be used, giving the amount by which the minimum and maximum of the +actual range of \code{x} should be expanded. For example, if a vector range from +5 to 15 and \code{add = 1}, the range will be expanded from 4 to 16. If \code{add} is +of length 2, then the first value is used for the lower bound and the second +value for the upper bound.} \item{range}{Initial (old) range of values. If \code{NULL}, will take the range of the input vector (\code{range(x)}).} @@ -167,11 +167,10 @@ x <- 5:15 x # both will expand the range by 10\% rescale(x, multiply = 1.1) -rescale(x, add = 1) +rescale(x, add = 0.5) -# "expand" range by 50\% -rescale(x, multiply = 1.5) -rescale(x, add = 5) +# expand range by different values +rescale(x, add = c(1, 3)) # Specify list of multipliers d <- data.frame(x = 5:15, y = 5:15) diff --git a/tests/testthat/test-data_rescale.R b/tests/testthat/test-data_rescale.R index 53154b5da..9caf3ee16 100644 --- a/tests/testthat/test-data_rescale.R +++ b/tests/testthat/test-data_rescale.R @@ -120,8 +120,17 @@ test_that("data_rescale can expand range", { c(4.5, 5.6, 6.7, 7.8, 8.9, 10, 11.1, 12.2, 13.3, 14.4, 15.5), ignore_attr = TRUE ) - expect_equal(rescale(x, multiply = 1.1), rescale(x, add = 1), ignore_attr = TRUE) + expect_equal(rescale(x, multiply = 1.1), rescale(x, add = 0.5), ignore_attr = TRUE) expect_error(rescale(x, multiply = 0.9, add = 1), regex = "Only one of") + expect_error(rescale(x, multiply = c(1.2, 1.4)), regex = "The length of") + + # different values for add + expect_equal( + rescale(x, add = c(1, 3)), + c(4, 5.4, 6.8, 8.2, 9.6, 11, 12.4, 13.8, 15.2, 16.6, 18), + ignore_attr = TRUE + ) + expect_error(rescale(x, add = 1:3), regex = "The length of") # works with NA expect_equal( @@ -139,14 +148,28 @@ test_that("data_rescale can expand range", { d <- data.frame(x = 5:15, y = 5:15) expect_equal( rescale(d, multiply = 1.1), - rescale(d, add = 1), + rescale(d, add = 0.5), ignore_attr = TRUE ) expect_equal( rescale(d, multiply = list(x = 1.1, y = 0.5)), - rescale(d, add = list(x = 1, y = -5)), + rescale(d, add = list(x = 0.5, y = -2.5)), ignore_attr = TRUE ) + # data frames accept multiple add-values per column + out <- rescale(d, add = list(x = c(1, 3), y = c(2, 4))) + expect_equal( + out$x, + rescale(d$x, add = c(1, 3)), + ignore_attr = TRUE + ) + expect_equal( + out$y, + rescale(d$y, add = c(2, 4)), + ignore_attr = TRUE + ) + expect_error(rescale(d, multiply = 0.9, add = 1), regex = "Only one of") expect_error(rescale(d, multiply = list(x = 0.9, y = 2), add = list(y = 1)), regex = "Only one of") + expect_error(rescale(d, multiply = c(0.9, 1.5)), regex = "The length of") })