2017-08-03 71 views
1

考虑:近似匹配(all.equal的模拟相同)?

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

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

的根本原因是floating point precision做。然而,这会导致尝试使用match识别序列中的子序列的时候出了问题,例如:

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

是否有match的替代方案,是为all.equalidentical模拟?

+3

也许用'round'? 'match(round(tmp2,2),round(tmp1,2))' –

+0

这是个好主意,所以我只需要巧妙地选择数字参数。 – Alex

+0

@Alex - 'round'绝对适用于矢量。否则就没用了。 – thelatemail

回答

1

我们可以写一个自定义的match称为near.match,通过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

虽然我喜欢这个答案的逻辑(使用'double.eps'),我认为通过在逻辑中构建'round'可以获得更高的效率。功能 – Alex

+0

@Alex,我认为给予tol比较灵活,但缺点是效率较低。 – mt1022