如何四舍五入到最接近的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,但是这不适用于任意的四舍五入间隔。

在 R 中有更好的方法吗?

114801 次浏览

我认为你的代码只要稍加修改就能很好地工作:

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

I altered your function in two way:

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

如果你只是想四舍五入到最接近的10的幂,那么只需要定义:

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

This actually also works when x is a vector:

> 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 是一个向量时,上面的方法不起作用——现在已经太晚了:)

> 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) ,那么 James 回答似乎是最合适的。我的版本允许您获取任何值,并自动将其四舍五入到一个合理的“不错”值。上面的“ nice”向量的其他一些好的选择是: 1:10, c(1,5,10), seq(1, 10, 0.1)

If you have a range of values in your plot, for example [3996.225, 40001.893] then the automatic way should take into account both the size of the range and the magnitude of the numbers. And as 哈德利注意到, the pretty() function might be what you want.

The plyr library has a function round_any that is pretty generic to do all kinds of rounding. For example

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

The round function in R assigns special meaning to the digits parameter if it is negative.

四舍五入(x,数字 = 0)

四舍五入到负数位意味着四舍五入到10的幂次方,例如四舍五入(x,数字 = -2)到最接近的100位。

这意味着像下面这样的函数可以得到所需的 非常接近

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

The output looks like the following

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

向上/向下舍入到任意间隔

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

功能:

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

例子:

> 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

工作原理:

模运算符 %%确定第一个数除以第二个数的余数。将这个时间间隔加或减去你感兴趣的数字,实际上可以将这个数字“四舍五入”到你选择的时间间隔。

> 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

更新:

方便的 2-argument version:

rounder <- function(x,y) {
if(y >= 0) { x + (y - x %% y)}
else { x - (x %% abs(y))}
}

y值为 roundUp,而负 y值为 roundDown:

 # rounder(7, -4.5) = 4.5, while rounder(7, 4.5) = 9.

或者..。

Function that 自动循环向上或向下 based on standard rounding rules:

Round <- function(x,y) {
if((y - x %% y) <= x %% y) { x + (y - x %% y)}
else { x - (x %% y)}
}

Automatically rounds up if the x value is > halfway between subsequent instances of the rounding value y:

# Round(1.3,1) = 1 while Round(1.6,1) = 2
# Round(1.024,0.05) = 1 while Round(1.03,0.05) = 1.05

关于 四舍五入到任意数字的多重性,例如10,这里有一个简单的替代詹姆斯的答案。

它适用于任何被四舍五入的 真的数字(from)和任何被四舍五入到(to)的 real positive数字:

> 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

你会发现一个升级版的 汤米的回答考虑到几种情况:

  • Choosing between lower or higher bound
  • 考虑到负值和零值
  • 两个不同的尺度,以防你想函数舍入不同的大小数字。例如: 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)
}
}
}

如果你给 round ()的数字参数加上一个负数,R 会把它四舍五入到10,100的倍数等等。

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

我没有使用任何外部库或神秘的功能,它的工作试图这一点!

希望能帮到别人。

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

如果你总是想把一个数字 起来四舍五入到最接近的 X,你可以使用 ceiling函数:

#Round 354 up to the nearest 100:
> X=100
> ceiling(354/X)*X
[1] 400


#Round 47 up to the nearest 30:
> Y=30
> ceiling(47/Y)*Y
[1] 60

类似地,如果您总是希望四舍五入 放下,请使用 floor函数。如果您想简单地向上或向下舍入到最接近的 Z,则使用 round代替。

> Z=5
> round(367.8/Z)*Z
[1] 370
> round(367.2/Z)*Z
[1] 365

y为正数时,它将 x四舍五入到最接近 y的整数倍,当 y为负数时,它将向下:

rom=\(x,y)x+(y-x%%y)%%y
rom(8.69,.1) # 8.7
rom(8.69,-.1) # 8.6
rom(8.69,.25) # 8.75
rom(8.69,-.25) # 8.5
rom(-8.69,.25) # -8.5

这总是四舍五入到最接近的倍数,如 plyr(https://github.com/hadley/plyr/blob/34188a04f0e33c4115304cbcf40e5b1c7b85fedf/R/round-any.r)中的 round_any:

rnm=\(x,y)round(x/y)*y
rnm(8.69,.25) # 8.75
plyr::round_any(8.69,.25) # 8.75

round_any也可以给 ceiling作为第三个总是四舍五入的参数,或者给 floor作为总是四舍五入的参数:

plyr::round_any(8.51,.25,ceiling) # 8.75
plyr::round_any(8.69,.25,floor) # 8.5

可能会遗漏一些东西,但它是否不像下面这样容易:

some_number = 789
1000 * round(some_number/1000, 0)

生产一些圆形到1000的东西?