J'écris une fonction pour tracer des données. J'aimerais spécifier un nombre rond de Nice pour l'axe des y max
qui est supérieur au max de l'ensemble de données.
Plus précisément, j'aimerais une fonction foo
qui effectue les opérations 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
arrondi au 10 le plus proche, mais cela ne fonctionne pas pour des intervalles d’arrondis arbitraires.
Y a-t-il une meilleure façon de faire cela en R?
Si vous voulez juste arrondir à la puissance 10 la plus proche, définissez simplement:
roundUp <- function(x) 10^ceiling(log10(x))
Cela fonctionne aussi quand 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 numéro "Nice", vous devez d'abord définir ce qu'est un numéro "Nice". Ce qui suit nous permet de définir "Nice" en tant que vecteur avec des valeurs de base de Nice comprises entre 1 et 10. La valeur par défaut est définie sur les nombres pairs plus 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]]]]
}
Ce qui précède ne fonctionne pas lorsque x est un vecteur - trop tard dans la soirée pour le moment :)
> 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
[[MODIFIER]]
Si la question est de savoir comment arrondir à la valeur la plus proche spécifiée (telle que 10 ou 100), alors James réponse semble le plus approprié. Ma version vous permet de prendre n'importe quelle valeur et de l'arrondir automatiquement à une valeur raisonnablement "agréable". Quelques autres bons choix du vecteur "Nice" ci-dessus sont: 1:10, c(1,5,10), seq(1, 10, 0.1)
Si vous avez une plage de valeurs dans votre graphique, par exemple [3996.225, 40001.893]
, la méthode automatique doit tenir compte à la fois de la taille de la plage et de la magnitude des nombres. Et comme noté par Hadley , la fonction pretty()
pourrait être ce que vous voulez.
La bibliothèque plyr
a une fonction round_any
qui est 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
La fonction round dans R attribue une signification spéciale au paramètre digits s'il est négatif.
rond (x, chiffres = 0)
Arrondir à un nombre négatif de chiffres signifie arrondir à une puissance de dix; ainsi, par exemple, arrondir (x, chiffres = -2) arrondit à la centaine la plus proche.
Cela signifie qu'une fonction comme celle-ci obtientassez prochede 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
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
Si vous ajoutez un nombre négatif à l'argument digits de round (), R l'arrondira aux multiples de 10, 100, etc.
round(9, digits = -1)
[1] 10
round(89, digits = -1)
[1] 90
round(89, digits = -2)
[1] 100
Vous pouvez facilement arrondir les nombres à un intervalle spécifique à l’aide de opérateur modulo%%
.
La fonction:
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)
}
}
}
Exemples:
> 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
Comment ça marche:
L'opérateur modulo %%
détermine le reste de la division du premier nombre par le second. Ajouter ou soustraire cet intervalle à votre numéro d'intérêt peut essentiellement "arrondir" ce nombre à un intervalle de votre choix.
> 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
La pratique version à 2 arguments: _
rounder <- function(x,y) {
if(y >= 0) { x + (y - x %% y)}
else { x - (x %% abs(y))}
}
y
positif roundUp
, alors que y
négatif roundDown
:
# rounder(7, -4.5) = 4.5, while rounder(7, 4.5) = 9.
Ou....
Fonction qui automatiquement arrondit UP ou DOWN selon les règles d'arrondi standard
Round <- function(x,y) {
if((y - x %% y) <= x %% y) { x + (y - x %% y)}
else { x - (x %% y)}
}
Arrondit automatiquement si la valeur x
est >
à mi-chemin entre les instances suivantes de la valeur arrondie 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
En ce qui concerne le arrondi à la multiplicité d’un nombre arbitraire, par ex. 10, voici une alternative simple à la réponse de James.
Cela fonctionne pour tout nombre réel arrondi (from
) et tout nombre réel positif arrondi à (to
):
> RoundUp <- function(from,to) ceiling(from/to)*to
Exemple:
> 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
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:
=1e-09
, n'hésitez pas à modifier!) à la max(x)
si vous voulez un plus grand nombreJ'ai essayé cela sans utiliser aucune bibliothèque externe ou fonctionnalités cryptiques et cela fonctionne!
J'espère que ça aide quelqu'un.
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
Si vous voulez toujours arrondir un nombre en haut au X le plus proche, vous pouvez utiliser la fonction 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
De même, si vous voulez toujours arrondir vers le bas, utilisez la fonction floor
. Si vous voulez simplement arrondir au Z le plus proche, utilisez plutôt round
.
> Z=5
> round(367.8/Z)*Z
[1] 370
> round(367.2/Z)*Z
[1] 365
Vous trouverez une version améliorée de La réponse de Tommy qui prend en compte plusieurs cas:
En dessous du 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)
}
}
}