在数字(浮点)键上使用 all.equal 合并数据帧?

Merging dataframes with all.equal on numeric(float) keys?

我有两个数据框要根据数值合并,但是我在浮点精度方面遇到了问题。示例:

> df1 <- data.frame(number = 0.1 + seq(0.01,0.1,0.01), letters = letters[1:10])
> df2 <- data.frame(number = seq(0.11,0.2,0.01), LETTERS = LETTERS[1:10])
> (merged <- merge(df1, df2, by = "number", all = TRUE))
   number letters LETTERS
1    0.11       a       A
2    0.12    <NA>       B
3    0.12       b    <NA>
4    0.13       c       C
5    0.14       d       D
6    0.15    <NA>       E
7    0.15       e    <NA>
8    0.16       f       F
9    0.17       g       G
10   0.18       h       H
11   0.19       i       I
12   0.20       j       J

由于浮点精度问题,某些值(0.12 和 0.15)不匹配 discussed in this post。找到相等性的解决方案是使用 all.equal 函数来删除浮点伪影,但是我不相信在 merge 函数中有办法做到这一点。

目前,我通过将 number 列之一强制为一个字符然后在 merge 之后返回到一个数字来解决这个问题,但这有点笨拙;有人对此问题有更好的解决方案吗?

> df1c <- df1
> df1c[["number"]] <- as.character(df1c[["number"]])
> merged2 <- merge(df1c, df2, by = "number", all = TRUE)
> merged2[["number"]] <- as.numeric(merged2[["number"]])
> merged2
   number letters LETTERS
1    0.11       a       A
2    0.12       b       B
3    0.13       c       C
4    0.14       d       D
5    0.15       e       E
6    0.16       f       F
7    0.17       g       G
8    0.18       h       H
9    0.19       i       I
10   0.20       j       J

编辑:关于数据的更多信息

四舍五入到允许数字相等的精度级别。

> df1$number=round(df1$number,2)
> df2$number=round(df2$number,2)
> 
>  (merged <- merge(df1, df2, by = "number", all = TRUE))
   number letters LETTERS
1    0.11       a       A
2    0.12       b       B
3    0.13       c       C
4    0.14       d       D
5    0.15       e       E
6    0.16       f       F
7    0.17       g       G
8    0.18       h       H
9    0.19       i       I
10   0.20       j       J

如果您需要以编程方式选择精度级别,那么您应该告诉我们更多有关数据的信息,以及我们是否可以假设它始终是由于浮点不准确造成的。如果是这样,则四舍五入到小数点后 10 位应该没问题。 all.equal 函数使用 sqrt(.Machine$double.eps) ,通常实践中应该类似于 round( ..., 16).