How to round to the nearest 10 (or 100 or X)?

I am writing a function to plot data. I would like to indicate a good round number for the max axis Y, which is greater than the maximum of the data set.

In particular, I would like a function foo that does the following:

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

I got to

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

for rounding to the nearest 10, but this does not work for arbitrary rounding intervals.

Is there a better way to do this in R?

+68
r rounding
Jun 23 '11 at 10:11
source share
11 answers

If you just want to round to the nearest power of 10, then simply define:

 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 

... but if you want to round to a "good" number, you first need to determine what a "good" number is. The following allows us to define “good” as a vector with good basic values ​​from 1 to 10. By default, an even number plus 5 is set.

 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]]]] } 

Above does not work when x is a vector - too late in the evening right now :)

 > 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 

[[EDIT]]

If the question is how to round to the specified closest value (e.g. 10 or 100), then James's answer seems most appropriate. My version allows you to take any value and automatically round it to a fairly “good” value. Some other nice variations of the nice vector are: 1:10, c(1,5,10), seq(1, 10, 0.1)

If you have a range of values ​​on your chart, for example [3996.225, 40001.893] then the automatic method should take into account both the size of the range and the value of the numbers. And, as Hadley noted , the pretty() function may be exactly what you need.

+55
Jun 24 2018-11-11T00:
source share

The plyr library has a function round_any , which is quite universal for 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 
+111
Jun 24 2018-11-11T00:
source share

The circular function in R assigns special meaning to the digit parameter if it is negative.

round (x, digits = 0)

Rounding to a negative number of digits means rounding to ten, so, for example, round (x, digits = -2) is rounded to the nearest hundred.

This means that a function like the following gets pretty close to what you are asking.

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

The result is as follows

 foo(4) [1] 10 foo(6.1) [1] 10 foo(30.1) [1] 40 foo(100.1) [1] 110 
+26
Aug 25 '14 at 22:22
source share

What about:

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

What gives:

 > roundUp(c(4,6.1,30.1,100.1)) [1] 10 10 40 110 > roundUp(4,5) [1] 5 > roundUp(12,7) [1] 14 
+23
Jun 24 '11 at 13:33
source share

If you add a negative number to the argument of digits round (), R rounds it to a multiple of 10, 100, etc.

  round(9, digits = -1) [1] 10 round(89, digits = -1) [1] 90 round(89, digits = -2) [1] 100 
+15
Feb 24 '17 at 13:52
source share

Rounding ANY number Up / Down to ANY interval

You can easily round numbers to a specific interval using the modulo operator %% .

Function:

 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) } } } 

Examples:

 > 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 

How does it work:

The operator modulo %% determines the remainder of dividing the first number by the second. Adding or subtracting this interval to your number of interests can essentially "round" the number to the interval of your choice.

 > 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 



Update:

Convenient 2-argument version:

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

Positive y values ​​are roundUp , and negative y values ​​are roundDown :

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



Or....

A function that automatically rounds Up or Down based on standard rounding rules:

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

It is automatically rounded if the value x > in the middle 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 
+8
Sep 10 '15 at 17:22
source share

Regarding rounding to the multiplicity of an arbitrary number , for example. 10, here is a simple alternative to James.

It works for any rounded real number ( from ) and any real positive number rounded to ( to ):

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

Example:

 > 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 
+7
Dec 10 '15 at 11:42
source share

I think your code just works fine with a slight modification:

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

And your examples are executed:

 > 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 changed your function in two ways:

  • second argument added (for your specified X)
  • added a small value ( =1e-09 , feel free to change!) to max(x) if you want a larger number
+1
Jun 23 '11 at 23:14
source share

You will find an updated version of Tommy's answer , which takes into account several cases:

  • Choose between lower or upper bound
  • Given negative and zero values
  • two different good scales if you want the function to bypass in different ways small and large numbers. Example: 4 will be rounded to 0, and 400 will be rounded to 400.

Below code:

 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) } } } 
0
Sep 07 '16 at 11:41
source share

I tried this without using any external libraries or cryptic functions, and it works!

Hope this helps someone.

 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 
0
Oct 26 '17 at 10:13
source share

If you always want to round a number to the nearest X, you can use the ceiling function:

 #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 

Similarly, if you want to always round down, use the floor function. If you want to simply round up or down to the nearest Z, use round instead.

 > Z=5 > round(367.8/Z)*Z [1] 370 > round(367.2/Z)*Z [1] 365 
0
Jan 31 '19 at 22:53
source share



All Articles