我想根据数值合并两个数据帧,但是我遇到浮点精度问题。以下面的两个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
值很困难,因为系列不一定存储在日历时间内。
答案 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)
类似。