转换R中的数字

时间:2013-05-09 14:16:10

标签: r

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

“floor”操作表现为:

138  -> 100
1233 -> 1000

“天花板”操作表现为:

138  -> 200
1233 -> 2000

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

5 个答案:

答案 0 :(得分:12)

你可以分别提取指数:

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 函数(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

答案 1 :(得分:8)

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

R> x <- 138
R> signif(x,1)
[1] 100
R> x <- 1712
R> signif(x,1)
[1] 2000

答案 2 :(得分: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
}

答案 3 :(得分:1)

我玩regexing和天花板的功能来获得这个:

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

答案 4 :(得分:1)

使用@ juba的建议,这是一个不同的看法。要获得floorceil的回答,我们只需要稍微纠正一下:

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))
}
矢量化后

edit2:,功能稍慢(请参阅非矢量化版本的编辑历史记录)。对于小向量,它们仍然很快,但是不能像@ 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