3 votes

Problème de virgule flottante lors de l'utilisation de %in%.

J'ai des difficultés à utiliser %in% lorsqu'il s'agit d'un problème de virgule flottante, par ex.

> x = seq(0.05, 0.3, 0.01)
> x %in% seq(0.15, 0.3, 0.01)
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[25] FALSE  TRUE

Je sais que c'est à cause de la façon dont l'ordinateur stocke les points flottants, mais existe-t-il une fonction telle que dplyr::near qui pourrait être utilisé pour remplacer %in% ? dplyr::near(x, y) ne fonctionnera pas si la longueur de x est différent de y .

Merci beaucoup !

1voto

Tim Biegeleisen Points 53335

L'utilisation de flottants arrondis à deux décimales semble fonctionner :

x <- round(seq(0.05, 0.3, 0.01), 2)
x %in% round(seq(0.15, 0.3, 0.01), 2)

                                                                 ^^ 0.15
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE
[13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[25]  TRUE  TRUE   <-- 0.3

1voto

Ronak Shah Points 24715

Vous pourriez utiliser dplyr::near ici, mais comme near effectue une comparaison par paire et vous avez besoin de comparer avec n'importe quelle valeur dans le vecteur utilisez sapply .

check_values <- seq(0.15, 0.3, 0.01)
sapply(x, function(x) any(dplyr::near(x, check_values)))

#[1]  FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE
#[13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
#[25]  TRUE  TRUE

1voto

jay.sf Points 8160

Transformer as.character .

as.character(x) %in% as.character(seq(0.15, 0.3, 0.01))
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [10] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
# [19]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

Cela semble également fonctionner finement pour les cas plus compliqués. Pensez-y :

x <- c(.2999, .3, .2499, .25)
y <- c(.299, .3, .249, .25)

as.character(x) %in% as.character(y)
# [1] FALSE  TRUE FALSE  TRUE

Lorsque l'on arrondit, il faut calculer les chiffres correctement pour pouvoir généraliser,

round(x, 3) %in% round(y, 3)
# [1] TRUE TRUE TRUE TRUE
round(x, 4) %in% round(y, 4)
# [1] FALSE  TRUE FALSE  TRUE

qui peuvent être automatisés :

d <- max(nchar(c(x, y))) - 2
round(x, d) %in% round(y, d)
# [1] FALSE  TRUE FALSE  TRUE

Nous pourrions regrouper les deux solutions dans une fonction :

`%in2%` <- function(x, y) {
  d <- max(nchar(c(x, y))) - 2
  round(x, d) %in% round(y, d)
}
`%in3%` <- function(x, y) {
  as.character(x) %in% as.character(y)
}
x %in2% y
# [1] FALSE  TRUE FALSE  TRUE
x %in3% y
# [1] FALSE  TRUE FALSE  TRUE

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