I am looking for rounding up behaviour for numbers like 0.1298 to be displayed as 0.130 while keeping the trailing zero as a significant digit. This also needs to work for tables where the length of the decimals is different. I use signif() to round the data and it works fine except R loses the trailing zero, but it is needed for accuracy. Is there a working function for this?
does anyone have a good idea for me? Thanks a lot already!
I have tried modifying signif
mod_signif <- function(x,digits) {
sprintf(paste0('%#.',3,'g'), signif(x,digits))}
and this works fine for numbers up to 5 decimal places, after which the scientific writing kicks in.
> mod_signif(0.129554,3)
[1] "0.130"
> mod_signif(0.0129554,3)
[1] "0.0130"
> mod_signif(0.00129554,3)
[1] "0.00130"
> mod_signif(0.000129554,3)
[1] "0.000130"
> mod_signif(0.0000129554,3)
[1] "1.30e-05"
I would expect 0.0000130 in this case
If I try to counteract this with the format() function, I start going in circles because then i am going back to numeric and lose the zero again….
>Solution :
You could use scales::label_number(). Because of the way the labelers within the scales package work, this requires creating a function within the body of another function.
Also note that you’ll need to do some simple arithmetic to convert from arguments that signif() expects to those that label_number() expects.
library(scales)
label_nicely <- function(number, digits){
## I stole this from the documentation for base::round
## Pretty neat, huh?
round_to <- digits - ceiling(log10(abs(number)))
value <- round(number, round_to)
## accuracy is expected to be (e.g.) 0.01 rather than, say, 3
accuracy_arg <- 1 / 10^round_to
## Construct a labeller within the function run
labeller <- label_number(accuracy = accuracy_arg)
label <- labeller(value)
return(label)
}
label_nicely(0.129554,3)
#> [1] "0.130"
label_nicely(0.0000129554, 3)
#> [1] "0.0000130"
Created on 2023-09-15 with reprex v2.0.2
Edit:
The description of base::round tell us that signif(n, x) is equivalent to round(n, x - ceiling(log10(abs(n))). Using that trick, we can convert from ‘significant digits’ to ‘actual digits’, which we can pass to the accuracy argument of label_number() to get the required behaviour.