-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrobust_round.R
101 lines (93 loc) · 3.21 KB
/
robust_round.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# DIZtools - Utilities for 'DIZ' R Package Development
# Copyright (C) 2020-2023 Universitätsklinikum Erlangen, Germany
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#' @title Round numbers without problems.
#' @description Round numbers without problems.
#' @param x (numeric) The numeric input vector to round.
#' @param digits (int, optional) The number of digits after the decimal
#' separator to round to.
#' @param thousands_separator (string, optional) Used as mark between every 3
#' decimals before the decimal point.
#' @param decimal_separator (string, optional) The character to be used to
#' indicate the numeric decimal point.
#' @param lower_indicator (Boolaen, optional, default = TRUE) If the result is
#' (since it is rounded) zero: Should there be displayed a lower-indicator?
#' E.g. \code{DIZtools::robust_round(0.00001)} results internally in "0.00".
#' The more intuitive result therefore would be "<0.01", which can be enabled
#' using the parameter `lower_indicator == TRUE`.
#' @return Rounded numbers as string.
#' @examples{
#' robust_round(c(1.234567, 987123.987654321))
#' #> [1] "1.23" "987.99"
#' }
#' @export
#'
robust_round <- function(x,
digits = 2,
thousands_separator = "",
decimal_separator = ".",
lower_indicator = TRUE) {
stopifnot(
"The `digits` argument must be an integer >= 0" =
is.numeric(digits) && digits >= 0,
"The `lower_indicator` must be TRUE or FALSE" =
is.logical(lower_indicator)
)
res <- round(x, digits = digits) |>
format(
nsmall = digits,
trim = TRUE,
big.mark = thousands_separator,
decimal.mark = decimal_separator
)
if (lower_indicator) {
return(sapply(res, function(x) {
## Remove thousands- and decimal-separator:
x_tmp <- x
if (thousands_separator != "") {
x_tmp <- gsub(
pattern = thousands_separator,
replacement = "",
x = x_tmp,
fixed = TRUE
)
}
if (decimal_separator != "") {
x_tmp <- gsub(
pattern = decimal_separator,
replacement = "",
x = x_tmp,
fixed = TRUE
)
}
if (x_tmp |> as.numeric() == 0) {
## Rounded value would be zero, so return "<0.00" instead:
if (digits == 0) {
return("<1")
} else {
return(paste0(
"<0",
decimal_separator,
paste(rep(0, digits - 1), collapse = ""),
"1"
))
}
} else {
return(x)
}
}) |> unname())
}
return(res)
}