在数字(浮点)键上使用 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
编辑:关于数据的更多信息
- 我想让我的问题保持笼统,以使其更适用于其他人的问题,但似乎我可能需要更具体才能得到答案。
- 很可能与合并的所有问题都是由于浮点不准确造成的,但这可能有点难以确定。数据以一系列时间序列值、开始时间和频率的形式出现。然后将它们转换为时间序列 (
ts
) 对象,并调用许多函数从时间序列中提取特征(其中一个是 time
值),它作为数据返回框架。同时调用另一组函数以从时间序列中获取其他特征作为目标。也可能有其他系列获得生成的功能以补充原始系列。然后必须使用 time
值重新组合这些值。
- 不能存储为
POSIXct
: 这些过程中的每一个(特征提取、目标计算、合并)都必须能够独立发生并存储在CSV 类型格式,以便它可以传递到其他平台。存储为 POSIXct
值会很困难,因为该系列不一定按日历时间存储。
四舍五入到允许数字相等的精度级别。
> 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)
.
我有两个数据框要根据数值合并,但是我在浮点精度方面遇到了问题。示例:
> 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
编辑:关于数据的更多信息
- 我想让我的问题保持笼统,以使其更适用于其他人的问题,但似乎我可能需要更具体才能得到答案。
- 很可能与合并的所有问题都是由于浮点不准确造成的,但这可能有点难以确定。数据以一系列时间序列值、开始时间和频率的形式出现。然后将它们转换为时间序列 (
ts
) 对象,并调用许多函数从时间序列中提取特征(其中一个是time
值),它作为数据返回框架。同时调用另一组函数以从时间序列中获取其他特征作为目标。也可能有其他系列获得生成的功能以补充原始系列。然后必须使用time
值重新组合这些值。 - 不能存储为
POSIXct
: 这些过程中的每一个(特征提取、目标计算、合并)都必须能够独立发生并存储在CSV 类型格式,以便它可以传递到其他平台。存储为POSIXct
值会很困难,因为该系列不一定按日历时间存储。
四舍五入到允许数字相等的精度级别。
> 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)
.