web-dev-qa-db-fra.com

Arrondir à partir de 0,5

Oui, je sais pourquoi nous arrondissons toujours au nombre pair le plus proche si nous sommes exactement au milieu (c'est-à-dire 2,5 devient 2) de deux nombres. Mais quand je veux évaluer des données pour certaines personnes, ils ne veulent pas de ce comportement. Quelle est la méthode la plus simple pour obtenir ceci:

x <- seq(0.5,9.5,by=1)
round(x)

être 1,2,3, ..., 10 et non 0,2,2,4,4, ..., 10.

Edit: Pour clearify: 1.4999 devrait être 1 après l'arrondi. (Je pensais que ce serait évident)

52
jakob-r

Ce n'est pas ma propre fonction, et malheureusement, Je ne trouve pas où je l'ai eu en ce moment (initialement trouvé comme un commentaire anonyme sur le blog Statistiquement significatif ), mais il devrait vous aider avec ce dont vous avez besoin.

round2 = function(x, n) {
  posneg = sign(x)
  z = abs(x)*10^n
  z = z + 0.5
  z = trunc(z)
  z = z/10^n
  z*posneg
}

x est l'objet que vous souhaitez arrondir et n est le nombre de chiffres que vous arrondissez.

Un exemple

x = c(1.85, 1.54, 1.65, 1.85, 1.84)
round(x, 1)
# [1] 1.8 1.5 1.6 1.8 1.8
round2(x, 1)
# [1] 1.9 1.5 1.7 1.9 1.8
56

Si vous voulez quelque chose qui se comporte exactement comme round à l'exception de ces valeurs xxx.5, essayez ceci:

x <- seq(0, 1, 0.1)
x
# [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
floor(0.5 + x)
# [1] 0 0 0 0 0 1 1 1 1 1 1
32
flodel

Comme @CarlWitthoft l'a dit dans les commentaires, il s'agit de la norme IEC 60559 telle que mentionnée dans ?round:

Notez que pour arrondir un 5, la norme IEC 60559 devrait être utilisée, 'aller au chiffre pair'. Par conséquent, arrondir (0,5) est égal à 0 et arrondir (-1,5) est - 2. Cependant, cela dépend des services du système d'exploitation et de l'erreur de représentation (puisque par exemple 0,15 n'est pas représenté exactement, la règle d'arrondi s'applique au nombre représenté et non au nombre imprimé, et ainsi arrondir (0,15, 1) pourrait être soit 0,1 ou 0,2).

An explication supplémentaire par Greg Snow:

La logique derrière le round to even rule est que nous essayons de représenter une valeur continue sous-jacente et si x provient d'une distribution vraiment continue, alors la probabilité que x == 2,5 soit 0 et le 2,5 a probablement déjà été arrondi une fois à partir de n'importe quelle valeur entre 2,45 et 2,54999999999999 ..., si nous utilisons la règle d'arrondi à 0,5 que nous avons apprise à l'école primaire, le double arrondi signifie que les valeurs comprises entre 2,45 et 2,50 seront arrondies à 3 (ayant été arrondies en premier à 2,5). Cela aura tendance à biaiser les estimations vers le haut. Pour supprimer le biais, nous devons soit revenir avant l'arrondi à 2,5 (ce qui est souvent impossible à impossible), soit simplement arrondir la moitié du temps et arrondir la moitié du temps (ou mieux serait d'arrondir proportionnel à la probabilité doivent voir des valeurs inférieures ou supérieures à 2,5 arrondies à 2,5, mais qui seront proches de 50/50 pour la plupart des distributions sous-jacentes). L'approche stochastique consisterait à faire en sorte que la fonction d'arrondi choisisse aléatoirement le chemin à arrondir, mais les types déterministes ne sont pas compatibles avec cela. de haut en bas environ 50/50.

Si vous traitez des données où 2,5 est susceptible de représenter une valeur exacte (de l'argent par exemple), vous pouvez faire mieux en multipliant toutes les valeurs par 10 ou 100 et en travaillant en nombres entiers, puis en effectuant une reconversion uniquement pour l'impression finale. Notez que 2,50000001 arrondit à 3, donc si vous conservez plus de chiffres de précision jusqu'à l'impression finale, l'arrondi ira dans la direction attendue, ou vous pouvez ajouter 0,00000000001 (ou un autre petit nombre) à vos valeurs juste avant l'arrondi, mais cela peut biaisez vos estimations vers le haut.

7
Jaap

Cela semble fonctionner:

rnd <- function(x) trunc(x+sign(x)*0.5)

La réponse d'Ananda Mahto semble faire cela et plus encore - je ne sais pas ce que le code supplémentaire dans sa réponse représente; ou, en d'autres termes, je ne peux pas comprendre comment briser la fonction rnd () définie ci-dessus.

Exemple:

seq(-2, 2, by=0.5)
#  [1] -2.0 -1.5 -1.0 -0.5  0.0  0.5  1.0  1.5  2.0
round(x)
#  [1] -2 -2 -1  0  0  0  1  2  2
rnd(x)
#  [1] -2 -2 -1 -1  0  1  1  2  2
5
user1854990

Selon la façon dont vous vous sentez à l'aise pour manipuler vos données, cela fonctionne:

round(x+10*.Machine$double.eps)
# [1]  1  2  3  4  5  6  7  8  9 10
3
MichaelChirico