与all.equal

时间:2016-10-21 18:22:23

标签: r merge floating-accuracy

我想根据数值合并两个数据帧,但是我遇到浮点精度问题。以下面的两个data.frames为例:

> 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

由于浮点精度问题为discussed in this post,某些值(0.12和0.15)不匹配。找到相等性的解决方案是使用all.equal函数来移除浮点工件,但我不相信在merge函数中有办法做到这一点。目前我通过将number列中的一个强制转换为一个字符,然后在合并后将其转回一个数字来绕过它,但这有点笨重。

> 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

有没有人有更好的解决方案来解决这个问题?

谢谢!

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

我想让我的问题保持一般性,使其更适用于其他人的问题,但似乎我可能需要更具体来获得答案。

合并的所有问题可能都是由于浮点不准确,但可能有点难以确定。数据以一系列时间序列值,开始时间和频率形式出现。然后将它们转换为时间序列(ts)对象,并调用许多函数从时间序列中提取要素(其中一个是time值),该数据作为数据返回帧。同时调用另一组函数以将时间序列中的其他特征作为目标。还可能会生成其他系列获取功能以补充原始系列。然后必须使用time值重新组合这些值。

这些过程(特征提取,目标计算,合并)中的每一个都必须能够独立发生并以CSV类型格式存储,以便可以传递到其他平台。存储为POSIXct值很困难,因为系列不一定存储在日历时间内。

1 个答案:

答案 0 :(得分:1)

舍入到允许数字相等的精度水平。

> 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)类似。