Vectorized Equality Testing

I would be surprised if it were not a duplicate, but I could not find a solution.

I understand the limitations of == to check if floating point numbers are equal. Need to use all.equal

 0.1 + 0.2 == 0.3 # FALSE all.equal(0.1 + 0.2, 0.3) # TRUE 

But == has the advantage of being vectorized:

 set.seed(1) Df <- data.frame(x = sample(seq(-1, 1, by = 0.1), size = 100, replace = TRUE), y = 0.1) Df[Df$x > 0 & Df$x < 0.2,] ## xy ## 44 0.1 0.1 ## 45 0.1 0.1 # yet sum(Df$x == Df$y) # [1] 0 

I can write the (bad) function myself:

 All.Equal <- function(x, y){ stopifnot(length(x) == length(y)) out <- logical(length(x)) for (i in seq_along(x)){ out[i] <- isTRUE(all.equal(x[i], y[i])) } out } sum(All.Equal(Df$x, Df$y)) 

which gives the correct answer, but still has a long way to go.

 microbenchmark::microbenchmark(All.Equal(Df$x, Df$y), Df$x == Df$y) Unit: microseconds expr min lq mean median uq max neval cld All.Equal(Df$x, Df$y) 9954.986 10298.127 20382.24436 10511.5360 10798.841 915182.911 100 b Df$x == Df$y 16.857 19.265 29.06261 30.8535 38.529 45.151 100 a 

Another option could be:

 All.equal.abs <- function(x,y){ tol <- .Machine$double.eps ^ 0.5 abs(x - y) < tol } 

which performs a comparison with == .

What is an existing function that performs this task?

+5
source share
2 answers

Vectorize() is slow. As @fishtank points out in the comment, the best solution is to check if the absolute difference is less than some tolerance value, i.e. is_equal_tol() below.

 set.seed(123) a <- sample(1:10, size = 50, replace = T) b <- sample(a) is_equal_tol <- function(x, y, tol = .Machine$double.eps ^ 0.5) { abs(x - y) < tol } is_equal_vec <- Vectorize(all.equal, c("target", "current")) is_equal_eq <- function(x, y) x == y microbenchmark::microbenchmark(is_equal_eq(a, b), is_equal_tol(a, b), isTRUE(is_equal_vec(a, b)), times = 1000L) Unit: nanoseconds expr min lq mean median uq max neval is_equal_eq(a, b) 0 856 1545.797 1284 2139 14113 1000 is_equal_tol(a, b) 1711 2567 4991.377 4278 6843 27370 1000 isTRUE(is_equal_vec(a, b)) 2858445 3008552 3258916.503 3082964 3204204 46130260 1000 
+2
source

It is not possible to run a test test, but embedding the all.equal function in it may work:

 All.equal <- Vectorize(all.equal, c("target", "current")) sum(All.equal(Df$x, Df$y)==T) 
0
source

Source: https://habr.com/ru/post/1241863/


All Articles