87 votes

Comment arrondir au 10 (ou au 100 ou au X) le plus proche?

J'écris une fonction pour tracer des données. Je voudrais spécifier un nombre rond intéressant pour le max d'axe des ordonnées supérieur au max du jeu de données.

Plus précisément, j'aimerais une fonction foo qui effectue les tâches suivantes:

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

J'ai eu jusqu'à

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

Pour le cas de 10, 100, mais cela ne fonctionne pas pour X arbitraire.

Y a-t-il une meilleure façon de faire cela en R?

123voto

Ramnath Points 24798

La bibliothèque plyr a une fonction round_any assez générique pour effectuer toutes sortes d’arrondis. Par exemple

 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
 

60voto

Tommy Points 16323

Si vous voulez juste pour arrondir jusqu'à la prise électrique la plus proche de 10, puis il suffit de définir:

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

Cela fonctionne également lorsque x est un vecteur:

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

..mais si vous voulez arrondir à un "gentil", numéro, vous devez d'abord définir ce qu'est un "gentil", le numéro est. La suite permet jusqu'à définir le "gentil" comme un vecteur avec des belles valeurs de base de 1 à 10. La valeur par défaut est le même nombres de plus de 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]]]]
}

Le ci-dessus ne fonctionne pas, lorsque x est un vecteur - trop tard dans la soirée, tout de suite :)

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

Si la question est comment faire pour arrondir une valeur la plus proche (10 ou 100), puis James réponse semble la plus appropriée. Ma version vous permet de prendre n'importe quelle valeur et automatiquement autour d'elle un assez "sympa" de la valeur. Quelques autres bons choix de le "gentil" vecteur ci-dessus sont: 1:10, c(1,5,10), seq(1, 10, 0.1)

Si vous avez une plage de valeurs de votre parcelle de terrain, par exemple [3996.225, 40001.893] puis la manière automatique et doit prendre en compte à la fois de la taille de la portée et de l'ampleur des nombres. Et comme indiqué par le Hadley, la jolie() la fonction peut-être ce que vous voulez.

41voto

Zero Points 366

La fonction round dans la R attribue une signification particulière pour les chiffres paramètre s'il est négatif.

round(x, chiffres = 0)

L'arrondi d'un nombre négatif de chiffres moyens de l'arrondi à une puissance de dix, de sorte par exemple round(x, chiffres = -2) est arrondi à la centaine la plus proche.

Cela signifie qu'une fonction comme suit obtient assez proche de ce que vous demandez.

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

La sortie ressemble à la suivante

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

24voto

James Points 24725

Que diriez-vous:

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

Qui donne:

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

2voto

daroczig Points 11126

Je pense que votre code fonctionne très bien avec une petite modification:

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

Et vos exemples courent:

 > 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
 

J'ai modifié votre fonction de deux manières:

  • deuxième argument ajouté (pour votre X spécifié)
  • ajouté une petite valeur ( =1e-09 , n'hésitez pas à modifier!) au max(x) si vous voulez un plus grand nombre

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X