如何凑到最近的10(或100或X)?

我正在写一个函数来绘制数据。 我想为大于数据集的最大值的y轴max指定一个不错的回合数。

具体来说,我想要一个执行以下操作的函数foo

 foo(4) == 5 foo(6.1) == 10 #maybe 7 would be better foo(30.1) == 40 foo(100.1) == 110 

我已经得到了

 foo <- function(x) ceiling(max(x)/10)*10 

对于最接近10,100的情况,但是这对于任意的X不起作用。

R中有更好的方法吗?

如果你只是想把最近的10次方加起来,那么就定义:

 roundUp <- function(x) 10^ceiling(log10(x)) 

当x是一个向量时,这实际上也起作用:

 > roundUp(c(0.0023, 3.99, 10, 1003)) [1] 1e-02 1e+01 1e+01 1e+04 

..但如果你想要一个“好”的数字,你首先需要定义一个“好”的数字是什么。 下面让我们将“nice”定义为一个向量,其基数值从1到10。默认设置为偶数加5。

 roundUpNice <- function(x, nice=c(1,2,4,5,6,8,10)) { if(length(x) != 1) stop("'x' must be of length 1") 10^floor(log10(x)) * nice[[which(x <= 10^floor(log10(x)) * nice)[[1]]]] } 

当x是一个vector时,上面的方法是行不通的 – 现在晚上太晚了:)

 > roundUpNice(0.0322) [1] 0.04 > roundUpNice(3.22) [1] 4 > roundUpNice(32.2) [1] 40 > roundUpNice(42.2) [1] 50 > roundUpNice(422.2) [1] 500 

[[编辑]]

如果问题是如何四舍五入到一个指定的最近值(如10或100),那么詹姆斯的答案似乎是最合适的。 我的版本可以让你采取任何价值,并自动把它合理的“好”价值。 上面的“好”向量的一些其他的好select是: 1:10, c(1,5,10), seq(1, 10, 0.1) : 1:10, c(1,5,10), seq(1, 10, 0.1)

如果你的图中有一个范围的值,例如[3996.225, 40001.893]那么自动方式应该考虑范围的大小和数量的大小。 正如Hadley指出的那样,pretty()函数可能就是你想要的。

plyr库有一个函数round_any ,它是非常通用的,可以进行各种舍入。 例如

 library(plyr) round_any(132.1, 10) # returns 130 round_any(132.1, 10, f = ceiling) # returns 140 round_any(132.1, 5, f = ceiling) # returns 135 

怎么样:

 roundUp <- function(x,to=10) { to*(x%/%to + as.logical(x%%to)) } 

这使:

 > roundUp(c(4,6.1,30.1,100.1)) [1] 10 10 40 110 > roundUp(4,5) [1] 5 > roundUp(12,7) [1] 14 

R中的圆整函数如果为负数,则对数字参数赋予特殊的含义。

round(x,digits = 0)

四舍五入到数字的负数表示四舍五入到十的数,例如round(x,digits = -2)到最近的一百。

这意味着像下面这样的函数非常接近你所要求的。

 foo <- function(x) { round(x+5,-1) } 

输出如下所示

 foo(4) [1] 10 foo(6.1) [1] 10 foo(30.1) [1] 40 foo(100.1) [1] 110 

关于任意数字 (例如10) 的多样性 ,这里是詹姆斯答案的简单替代。

它适用于任何数(四舍五入)和任何实际的正数四舍五入到():

 > RoundUp <- function(from,to) ceiling(from/to)*to 

例:

 > RoundUp(-11,10) [1] -10 > RoundUp(-0.1,10) [1] 0 > RoundUp(0,10) [1] 0 > RoundUp(8.9,10) [1] 10 > RoundUp(135,10) [1] 140 > RoundUp(from=c(1.3,2.4,5.6),to=1.1) [1] 2.2 3.3 6.6 

如果向round()的digits-argument添加一个负数,R会将其舍入到10,100等的倍数。

  round(9, digits = -1) [1] 10 round(89, digits = -1) [1] 90 round(89, digits = -2) [1] 100 

我认为你的代码只需要很小的修改即可:

 foo <- function(x, round=10) ceiling(max(x+10^-9)/round + 1/round)*round 

你的例子运行:

 > foo(4, round=1) == 5 [1] TRUE > foo(6.1) == 10 #maybe 7 would be better [1] TRUE > foo(6.1, round=1) == 7 # you got 7 [1] TRUE > foo(30.1) == 40 [1] TRUE > foo(100.1) == 110 [1] TRUE > # ALL in one: > foo(c(4, 6.1, 30.1, 100)) [1] 110 > foo(c(4, 6.1, 30.1, 100), round=10) [1] 110 > foo(c(4, 6.1, 30.1, 100), round=2.3) [1] 101.2 

我用两种方式改变了你的function:

  • 添加第二个参数(对于您指定的X
  • 如果你想要一个更大的数字,可以添加一个小的值( =1e-09 ,随意修改!)到max(x)

您可以使用模运算符 %%轻松地将数字四舍五入到特定的时间间隔。

首先是一个通用function:

 round.choose <- function(x, round.val, dir = 1) { if(dir == 1) { ##ROUND UP x + (round.val - x %% round.val) } else { if(dir == 0) { ##ROUND DOWN x - (x %% round.val) } } } 

例子:

 > round.choose(17,5,1) #round 17 UP to the next 5th [1] 20 > round.choose(17,5,0) #round 17 DOWN to the next 5th [1] 15 > round.choose(17,2,1) #round 17 UP to the next even number [1] 18 > round.choose(17,2,0) #round 17 DOWN to the next even number [1] 16 

怎么运行的:

模运算符%%决定了第一个数除以第二个数的余数。 增加或减less这个时间间隔到你感兴趣的数字,可以基本上将数字“四舍五入”到你select的时间间隔。

 > 7 + (5 - 7 %% 5) #round UP to the nearest 5 [1] 10 > 7 + (10 - 7 %% 10) #round UP to the nearest 10 [1] 10 > 7 + (2 - 7 %% 2) #round UP to the nearest even number [1] 8 > 7 + (100 - 7 %% 100) #round UP to the nearest 100 [1] 100 > 7 + (4 - 7 %% 4) #round UP to the nearest interval of 4 [1] 8 > 7 + (4.5 - 7 %% 4.5) #round UP to the nearest interval of 4.5 [1] 9 > 7 - (7 %% 5) #round DOWN to the nearest 5 [1] 5 > 7 - (7 %% 10) #round DOWN to the nearest 10 [1] 0 > 7 - (7 %% 2) #round DOWN to the nearest even number [1] 6 

你会发现Tommy的答案的升级版本,考虑到几种情况:

  • select较低或较高的范围
  • 考虑到负值和零值
  • 两个不同的好规模,以防你想要的function绕不同的小数和大数。 例如:4将被舍入为0,而400将被舍入为400。

下面的代码:

 round.up.nice <- function(x, lower_bound = TRUE, nice_small=c(0,5,10), nice_big=c(1,2,3,4,5,6,7,8,9,10)) { if (abs(x) > 100) { nice = nice_big } else { nice = nice_small } if (lower_bound == TRUE) { if (x > 0) { return(10^floor(log10(x)) * nice[[max(which(x >= 10^floor(log10(x)) * nice))[[1]]]]) } else if (x < 0) { return(- 10^floor(log10(-x)) * nice[[min(which(-x <= 10^floor(log10(-x)) * nice))[[1]]]]) } else { return(0) } } else { if (x > 0) { return(10^floor(log10(x)) * nice[[min(which(x <= 10^floor(log10(x)) * nice))[[1]]]]) } else if (x < 0) { return(- 10^floor(log10(-x)) * nice[[max(which(-x >= 10^floor(log10(-x)) * nice))[[1]]]]) } else { return(0) } } } 

我试过这个,不用任何外部库或神秘的function,它的工作原理!

希望它可以帮助别人。

 ceil <- function(val, multiple){ div = val/multiple int_div = as.integer(div) return (int_div * multiple + ceiling(div - int_div) * multiple) } > ceil(2.1, 2.2) [1] 2.2 > ceil(3, 2.2) [1] 4.4 > ceil(5, 10) [1] 10 > ceil(0, 10) [1] 0