Reputation: 38639
The signif()
function rounds values based on the specificed number of
significant digits in a given value. The function applies to all the
digits in the number, though, so numbers of different orders of
magnitude are rounded and truncated differently. For instance, with this
vector x
…
x <- c(100.1303421, 10.03421, 1.3421, 0.0003421)
lapply(x, signif, 2)
#> [[1]]
#> [1] 100
#>
#> [[2]]
#> [1] 10
#>
#> [[3]]
#> [1] 1.3
#>
#> [[4]]
#> [1] 0.00034
… the first and second values are truncated to 100 and 10 and the
decimal values disappear, while the third and fourth values maintain
decimals (though different numbers). This is the expected output from
signif()
—it rightfully takes into account all the digits when
determining significant.
Is it possible to ignore the integer part of each number and only format
the decimal part with a set number of significant digits? I'd like to be
able to return these values: c(100.13, 10.034, 1.34, 0.00034)
; that
is, the complete integer preceding the .
, followed by the significant
digits of the decimal portion of the number.
For now, I've created a function that separates values into integer and
fraction components and runs signif()
only on the fraction component,
but this seems exceptionally hacky.
signif_ignore_integer <- function(x, digits = 2) {
as.integer(x) + signif(x - as.integer(x), digits)
}
lapply(x, signif_ignore_integer, 2)
#> [[1]]
#> [1] 100.13
#>
#> [[2]]
#> [1] 10.034
#>
#> [[3]]
#> [1] 1.34
#>
#> [[4]]
#> [1] 0.00034
Is there a better, more recommended way (possibly with some fancy
sprintf()
format) to round values to a given number of significant
digits while ignoring their integer components?
Upvotes: 4
Views: 3709
Reputation: 93811
There may be a better way, but your general approach doesn't seem unreasonable. However, you can streamline it by using floor
, taking advantage of vectorization to avoid lapply
, and using the mod operator to return the fractional part of each number:
my_signif = function(x, digits) floor(x) + signif(x %% 1, digits)
my_signif(x, 2)
[1] 100.13000 10.03400 1.34000 0.00034
Upvotes: 1