我有一个增加数字的向量,如下所示:
set.seed(1)
numbers <- cumsum(abs(rnorm(10,100,100)))
# [1] 37.35462 155.71895 172.15609 431.68417 564.63495 582.58811 731.33101 905.16348 1062.74162 1132.20278
Run Code Online (Sandbox Code Playgroud)
我想选择最小数量的有效数字,然后舍入这些数字,确保我始终保持足够的数字,以便连续的数字不会四舍五入到相同的值.
请参阅以下示例(预期输出):
magic(numbers, n = 1)
# [1] 40 160 170 400 560 580 700 900 1060 1130
Run Code Online (Sandbox Code Playgroud)
37.35462四舍五入到40因为我在这里只要求一位数(n = 1)155.71895到200,因为172.15609会被四舍五入到200太受同样的规则,所以我圆155.71895到160,并172.15609以170431.68417到400,因为它是远远不够的172.15609,并564.63495等等...
对于n = 2或3,我们将获得:
magic(numbers, n = 2)
# [1] 37 160 170 430 560 580 730 910 1060 1130
magic(numbers, n = 3)
# [1] 37.4 156 172 432 565 583 731 905 1060 1130
Run Code Online (Sandbox Code Playgroud)
我的目标是获得非线性分布的分位数的可读值.
#' Minimum preferred significant digits
#'
#' @details
#' Facilitate reducing numbers to their least *distinguishable*
#' significant digits, where "distinguishable" means
#' "between neighbors". This means that if reducing more digits would
#' cause two neighbors to reduce to the same number, then the
#' reduction cannot take place.
#'
#' References:
#'
#' - [Original question on StackOverflow](https://stackoverflow.com/q/51616332/3358272) (and [my answer](https://stackoverflow.com/a/51617325/3358272))
#'
#' @param numbers numeric, length 2 or more
#' @param n integer, number of preferred remaining significant digits
#' @return numeric vector
#' @export
#' @md
#' @examples
#' \dontrun{
#' set.seed(1)
#' numbers <- cumsum(abs(rnorm(10,100,100)))
#' # [1] 37.35462 155.71895 172.15609 431.68417 564.63495 582.58811 731.33101 905.16348 1062.74162 1132.20278
#' magic(numbers, 1)
#' # [1] 40 160 170 400 560 580 700 900 1060 1130
#' magic(numbers, 2)
#' # [1] 37 160 170 430 560 580 730 910 1060 1130
#' magic(numbers, 3)
#' # [1] 37.4 156.0 172.0 432.0 565.0 583.0 731.0 905.0 1060.0 1130.0
#' magic(c(1,2.4,2.6,4),1)
#' # [1] 1 2 3 4
#' }
magic <- function(numbers, n=1L) {
stopifnot(length(numbers) > 1L)
logscale <- ceiling(log10(abs(numbers)))
logdiff <- log10(diff(numbers))
keepoom <- floor(pmin(c(Inf, logdiff), c(logdiff, Inf)))
roundpoints <- 5*(10^keepoom)
out <- signif(numbers, pmax(n, logscale - (1+keepoom)))
dupes <- duplicated(out)
if (any(dupes)) {
dupes <- dupes | c(dupes[-1], FALSE)
out2 <- signif(numbers, pmax(n, logscale - keepoom))
out[dupes] <- out2[dupes]
}
out
}
Run Code Online (Sandbox Code Playgroud)
样品用法:
magic(numbers, 1)
# [1] 40 160 170 400 560 580 700 900 1060 1130
## [1] 40 160 170 400 560 580 700 900 1060 1130 # yours
magic(numbers, 2)
# [1] 37 160 170 430 560 580 730 910 1060 1130
## [1] 37 160 170 430 560 580 730 910 1060 1130 # yours
magic(numbers, 3)
# [1] 37.4 156.0 172.0 432.0 565.0 583.0 731.0 905.0 1060.0 1130.0
## [1] 37.4 156 172 432 565 583 731 905 1060 1130 # yours
magic(c(1,2.4,2.6,4),1)
# [1] 1 2 3 4
## [1] 1:4 # yours, from comments
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |