2017-08-03 2 views
1

Bedenken Sie:Ungefähre Übereinstimmung (analog aller gleich für identisch)?

(tmp1 <- seq(0, 0.2, 0.01)[16]) 
# [1] 0.15 
(tmp2 <- seq(0, 0.2, 0.05)[4]) 
# [1] 0.15 

und

identical(tmp1, tmp2) 
# [1] FALSE 
all.equal(tmp1, tmp2) # test for 'near' equality 
[1] TRUE 

Der eigentliche Grund ist mit floating point precision zu tun. Dies führt jedoch zu einem Problem, wenn sie versuchen, Teilfolgen innerhalb Sequenzen zu identifizieren match verwenden, zum Beispiel:

match(seq(0, 0.2, 0.05), seq(0, 0.2, 0.01)) 
# [1] 1 6 11 NA 21 

Gibt es eine Alternative zu match, die das Analogon von all.equal für identical ist?

+3

Vielleicht mit 'round'? 'match (round (tmp2, 2), round (tmp1, 2))' –

+0

Das ist eine gute Idee, also muss ich nur geschickt das Ziffernargument wählen. – Alex

+0

@Alex - 'round' funktioniert definitiv auf Vektoren. Es wäre sonst ziemlich nutzlos. – thelatemail

Antwort

1

Wir können eine benutzerdefinierte schreiben matchnear.match genannt, inspiriert von dplyr::near:

near.match <- function(x, y, tol = .Machine$double.eps^0.5){ 
    sapply(x, function(i){ 
     res <- which(abs(y - i) < tol, arr.ind = TRUE)[1] 
     if(length(res)) res else NA_integer_ 
    }) 
} 

near.match(seq(0, 0.2, 0.05), seq(0, 0.2, 0.01)) 
# [1] 1 6 11 16 21 
near.match(c(seq(0, 0.2, 0.05), 0.3), seq(0, 0.2, 0.01)) 
# [1] 1 6 11 16 21 NA 
+0

während ich die Logik dieser Antwort (mit 'double.eps') mag, denke ich, mehr Effizienz kann durch den Aufbau in Ihrer Logik der' Runde' erhalten werden Funktion – Alex

+0

@Alex, ich denke, ein 'Tol 'geben ist flexibler, während der Nachteil ist weniger Effizienz. – mt1022

Verwandte Themen