9

我特别需要在 R 中“转换”一个数字。例如,

“地板”操作表现为:

138  -> 100
1233 -> 1000

“天花板”操作表现为:

138  -> 200
1233 -> 2000

有没有一种简单的方法可以在 R 中实现这一点?谢谢

4

5 回答 5

13

您可以分别提取指数:

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))) 以加快计算速度
  • 添加基准以与@eddi 进行比较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
于 2013-05-09T14:23:48.607 回答
8

它不会直接回答您的问题,但您也可以看看signif

R> x <- 138
R> signif(x,1)
[1] 100
R> x <- 1712
R> signif(x,1)
[1] 2000
于 2013-05-09T14:25:52.547 回答
5

另外的选择:

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
}
于 2013-05-09T14:48:46.763 回答
1

我玩了正则表达式和天花板地板功能来获得这个:

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
于 2013-05-09T14:43:04.437 回答
1

这是使用@juba 的建议的不同方法。要获得对flooror的全面答案,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
于 2013-05-09T18:06:58.920 回答