diff --git a/R/options.R b/R/options.R index 31497dbd..43409a91 100644 --- a/R/options.R +++ b/R/options.R @@ -8,6 +8,7 @@ assign(".units.auto_convert_names_to_symbols", NA, envir = .units_options) assign(".units.simplify", NA, envir = .units_options) assign(".units.allow_mixed", NA, envir = .units_options) assign(".units.unitless_symbol", NA, envir = .units_options) +assign(".units.convert_to_base", NA, envir = .units_options) #' set one or more units global options @@ -23,6 +24,7 @@ assign(".units.unitless_symbol", NA, envir = .units_options) #' @param simplify logical, default \code{NA}; simplify units in expressions? #' @param allow_mixed logical; if \code{TRUE}, combining mixed units creates a \code{mixed_units} object, if \code{FALSE} it generates an error #' @param unitless_symbol character; set the symbol to use for unitless (1) units +#' @param convert_to_base logical; if \code{TRUE}, convert units to (SI) base units #' @details This sets or gets units options. Set them by using named arguments, get them by passing the option name. #' #' The default \code{NA} value for \code{simplify} means units are not simplified in \link{set_units} or \link{as_units}, but are simplified in arithmetical expressions. @@ -35,7 +37,7 @@ assign(".units.unitless_symbol", NA, envir = .units_options) #' units_options("group") #' @export units_options = function(..., sep, group, negative_power, parse, set_units_mode, auto_convert_names_to_symbols, simplify, - allow_mixed, unitless_symbol) { + allow_mixed, unitless_symbol, convert_to_base) { # op = as.list(units:::.units_options) ret = list() if (!missing(sep)) { @@ -83,6 +85,11 @@ units_options = function(..., sep, group, negative_power, parse, set_units_mode, ret$unitless_symbol = get(".units.unitless_symbol", envir = .units_options) assign(".units.unitless_symbol", unitless_symbol, envir = .units_options) } + if (!missing(convert_to_base)) { + stopifnot(is.logical(convert_to_base)) + ret$convert_to_base = get(".units.convert_to_base", envir = .units_options) + assign(".units.convert_to_base", convert_to_base, envir = .units_options) + } dots = list(...) if (length(dots)) { @@ -105,7 +112,8 @@ units_options( auto_convert_names_to_symbols = TRUE, simplify = NA, allow_mixed = FALSE, - unitless_symbol = "1") # set defaults + unitless_symbol = "1", + convert_to_base = FALSE) # set defaults .units.simplify = function() { get(".units.simplify", envir = .units_options) diff --git a/R/symbolic_units.R b/R/symbolic_units.R index 7560f8f5..ff36ff0e 100644 --- a/R/symbolic_units.R +++ b/R/symbolic_units.R @@ -122,6 +122,14 @@ as.character.symbolic_units <- function(x, ..., paste(num_str, denom_str, sep = sep) } +to_base <- function(x) { # https://github.com/r-quantities/units/issues/132 + u_str = as.character(units(x)) + u = R_ut_parse(u_str) + ft = R_ut_format(u, ascii = TRUE) + new = as_units(strsplit(ft, " ")[[1]][2]) + set_units(x, new, mode = "standard") +} + .simplify_units <- function(value, sym_units) { simplify = .units.simplify() @@ -131,9 +139,12 @@ as.character.symbolic_units <- function(x, ..., return(value) } + if (isTRUE(units_options("convert_to_base"))) + return(to_base(value)) + # This is just a brute force implementation that takes each element in the # numerator and tries to find a value in the denominator that can be converted - # to the same unit. It modifies "value" to rescale the nominator to the denomiator + # to the same unit. It modifies "value" to rescale the nominator to the denominator # before removing matching units. drop_ones = function(u) u[ u != "1" ] diff --git a/man/units_options.Rd b/man/units_options.Rd index c81784f8..8529f636 100644 --- a/man/units_options.Rd +++ b/man/units_options.Rd @@ -5,7 +5,8 @@ \title{set one or more units global options} \usage{ units_options(..., sep, group, negative_power, parse, set_units_mode, - auto_convert_names_to_symbols, simplify, allow_mixed, unitless_symbol) + auto_convert_names_to_symbols, simplify, allow_mixed, unitless_symbol, + convert_to_base) } \arguments{ \item{...}{named options (character) for which the value is queried} @@ -27,6 +28,8 @@ units_options(..., sep, group, negative_power, parse, set_units_mode, \item{allow_mixed}{logical; if \code{TRUE}, combining mixed units creates a \code{mixed_units} object, if \code{FALSE} it generates an error} \item{unitless_symbol}{character; set the symbol to use for unitless (1) units} + +\item{convert_to_base}{logical; if \code{TRUE}, convert units to (SI) base units} } \value{ in case options are set, invisibly a named list with the option values that are being set; if an option is queried, the current option value.