2016-01-30 41 views
5

Bu bir çift olmadığında şaşırırdım, ancak bir çözüm bulamadım.Vectorized eşitlik testi

Kayan nokta sayılarının eşitliğini sınamak için == sınırlamalarını anlıyorum. işlev

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,] 
## x y 
## 44 0.1 0.1 
## 45 0.1 0.1 

# yet 
sum(Df$x == Df$y) 
# [1] 0 

Ben (kötü) yazabilirsiniz kendim: Bir all.equal

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

Ama == vectorized olma avantajına sahiptir kullanmalıdır

doğru cevabı verir
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)) 

, ama hala gitmek için uzun bir yol var.

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 

Başka bir seçenek olabilir: == denk şekilde gerçekleştirir

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

.

Bu görevi gerçekleştiren varolan bir işlev nedir?

+0

yakın Aklıma (Df, mapply (function (a, b) isTRUE (all.equal (a, b)), x, y)) 'ile' ama bu muhtemelen daha iyi olurdu Yaptığın şeyden daha iyi. '.mapply()' (çıplak kemikler mapply() ') kullanarak hafif bir hız artışı elde edebilirsiniz. –

+4

' abs (x-y) fishtank

cevap

0

bir kıyaslama testi yapamaz, ancak Vektörizasyonu all.equal işlevi işe yarayabilir:

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

Vectorize() yavaş seçenek olarak çıkıyor. @fishtank'ın yorumda öne sürdüğü gibi, en iyi çözüm, mutlak farkın bazı tolerans değerinden daha küçük olup olmadığını, yani is_equal_tol()'un aşağıdan mı olduğunu kontrol etmekten gelmektedir.

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 
+1

'a' ve' b' jenerasyonunuzu göstermezsiniz, ancak sonuçlarınız nanosaniye ile daha uzun vektörler yapmalısınız. – Gregor

+0

@Gregor Haklısınız. Örneği tam örnek vermek için düzenledim. Teşekkürler! –