我特别需要在 R 中“转换”一个数字。例如,
“地板”操作表现为:
138 -> 100
1233 -> 1000
“天花板”操作表现为:
138 -> 200
1233 -> 2000
有没有一种简单的方法可以在 R 中实现这一点?谢谢
我特别需要在 R 中“转换”一个数字。例如,
“地板”操作表现为:
138 -> 100
1233 -> 1000
“天花板”操作表现为:
138 -> 200
1233 -> 2000
有没有一种简单的方法可以在 R 中实现这一点?谢谢
您可以分别提取指数:
floorEx <- function(x) {
ex <- 10^trunc(log10(x))
return(trunc(x/ex)*ex)
}
ceilingEx <- function(x) {
ex <- 10^trunc(log10(x))
return(ceiling(x/ex)*ex)
}
例子:
floorEx(123)
# [1] 100
ceilingEx(123)
# [1] 200
ceilingEx(c(123, 1234, 12345))
# [1] 200 2000 20000
编辑:
trunc
代替floor
并集成旧的前函数 ( ex <- function(x)floor(log10(x))
) 以加快计算速度floorR
基准:
## provided by @eddi
floorR <- function(x) {r <- signif(x, 1); r - (r > x) * 10^trunc(log10(x))}
library("microbenchmark")
x <- 123; microbenchmark(floorEx(x), floorR(x), signif(x), times=1e4)
# Unit: nanoseconds
# expr min lq median uq max neval
# floorEx(x) 2182 2414 2521 2683.0 704190 10000
# floorR(x) 2894 3150 3278 3505.5 22260 10000
# signif(x) 372 472 507 556.0 10963 10000
x <- 1:1000; microbenchmark(floorEx(x), floorR(x), signif(x), times=1e2)
# Unit: microseconds
# expr min lq median uq max neval
# floorEx(x) 100.560 101.2460 101.6945 115.6385 818.895 100
# floorR(x) 354.848 355.4705 356.0420 375.9210 1074.582 100
# signif(x) 114.608 115.2120 115.4695 119.1805 186.738 100
它不会直接回答您的问题,但您也可以看看signif
:
R> x <- 138
R> signif(x,1)
[1] 100
R> x <- 1712
R> signif(x,1)
[1] 2000
另外的选择:
floor2 <- function(x) {
mag <- 10^(nchar(round(x))-1)
(x %/% mag) * mag
}
ceil2 <- function(x) {
mag <- 10^(nchar(round(x))-1)
((x + mag) %/% mag) * mag
}
我玩了正则表达式和天花板地板功能来获得这个:
ceil <- function(x) {
ceiling(as.numeric(sub("([[:digit:]])", "\\1.", x))) * (10^(nchar(x)-1))
}
flr <- function(x) {
floor(as.numeric(sub("([[:digit:]])", "\\1.", x))) * (10^(nchar(x)-1))
}
ceil(1233)
ceil(138)
flr(1233)
flr(138)
## > ceil(1233)
## [1] 2000
## > ceil(138)
## [1] 200
## > flr(1233)
## [1] 1000
## > flr(138)
## [1] 100
这是使用@juba 的建议的不同方法。要获得对floor
or的全面答案,ceil
我们只需要稍微纠正一下:
floorR = function(x) {
rounded = signif(x, 1);
rounded - (rounded > x) * 10^trunc(log10(x))
}
ceilR = function(x) {
rounded = signif(x, 1);
rounded + (rounded < x) * 10^trunc(log10(x))
}
编辑2 :矢量化后,功能有点慢(请参阅非矢量化版本的编辑历史)。对于小向量,它们仍然很快,但不能像@sgibb 的解决方案那样扩展(部分原因signif
是不能很好地扩展):
x = 156; microbenchmark(floorEx(x), flr(x), floor2(x), signif(x), floorR(x), times = 10000)
#Unit: nanoseconds
# expr min lq median uq max neval
# floorEx(x) 4008 8348 10018 12021 158934 10000
# flr(x) 84810 121204 135896 141571 6708248 10000
# floor2(x) 32055 46078 51086 54091 360606 10000
# signif(x) 0 1002 1336 1671 86813 10000
# floorR(x) 3006 6679 8348 10017 207683 10000
x = c(1:1000); microbenchmark(floorEx(x), signif(x), floorR(x), times = 100)
#Unit: microseconds
# expr min lq median uq max neval
# floorEx(x) 125.879 157.4315 158.934 161.4385 243.742 100
# signif(x) 147.581 216.6975 217.365 220.5375 395.998 100
# floorR(x) 252.758 360.6055 362.275 366.4485 619.373 100