fread/fwrite 引入垃圾值

fread/fwrite introduces garbage values

提问人:algae 提问时间:4/18/2022 最后编辑:algae 更新时间:4/19/2022 访问量:118

问:

数据文件:data.dat

5625010350032.36719 5627008621379.12591 5628763999478.55791 5630383772880.98831 5632384688238.96095 5633992371569.87936 5635830220975.76879 5637713568911.67183 5639436594135.51215 5641160625591.58400 5643072053703.23919 5644920788572.33232 5646668772882.99855 5648398453919.33759 5650178043246.84799 5651842484825.03887 5653671759113.42399 5655374735235.55599 5657184594518.72287 5658951103084.33839 5660687853998.58127 5662491073242.24399 

以下代码

x1 <- data.matrix(data.table::fread("data.dat")) # Read it
plot(x1[1,])                                     
data.table::fwrite(x=x1, file="xout.dat", sep=" ") # Write it 
x2 <- data.matrix(data.table::fread("xout.dat"))   # Read it again
lines(x2[1,], col='red')

显示该元素在实际上应该等于 时取值。是什么导致了垃圾值的引入?x2[1,13]2.7898250541260385e-311x1[1,13]

该文件按以下方式从 C++ 文件写入data.dat

    std::ofstream file("data.dat", std::ios::out);
    file << std::setprecision(std::numeric_limits<long double>::digits10) << std::showpoint;
    for (size_t i = 0; i < v.size(); ++i)
        file << v[i] << " ";
    file << std::endl;

其中,向量包含写入 的值。我正在使用 data.table 版本 1.14.2 和 R 4.1.3。vdata.dat

C++ R Data.Table 精度

评论


答:

2赞 Merijn van Tilborg 4/19/2022 #1

看起来,它在进程中的某个地方进行了一些舍入,fread 将第 13 个值存储为“integer64”(默认值),读取检测到包含大于 2^31 的整数的列,类型为 bit64::integer64integer64

enter image description here

你可以做的是通过添加到你的 fread 中来强制它被解释为数字。colClasses = c("numeric")

x2 <- data.matrix(data.table::fread("xout.dat", colClasses = c("numeric")))

这不能防止浮点问题,但不会完全更改第 13 个值。

如果我们现在做 x1-x2,我们会看到所有值都有相同的差异。

x1-x2

#              V1         V2         V3         V4         V5          V6          V7        V8        V9       V10         V11       V12
# [1,] -0.0029297 -0.0039062 -0.0019531 -0.0019531 0.00097656 -0.00097656 -0.00097656 0.0019531 0.0019531 0.0039062 -0.00097656 0.0019531
#              V13        V14        V15         V16       V17        V18       V19         V20        V21       V22
# [1,] -0.00097656 -0.0019531 -0.0019531 -0.00097656 0.0039062 -0.0039062 0.0029297 -0.00097656 0.00097656 0.0039062

评论

0赞 algae 4/20/2022
您能否扩展“这不能防止浮点问题”?奇怪的是,它可以读取到 16 位精度,但不能将其写入文件。例如,按预期工作,尽管我不想手动格式化等麻烦。这就是为什么我们首先使用软件包的原因。此外,我的问题不是写入和重新读取相同的数据 - 我正在读取、执行操作然后再次写入。我一直在阅读 fwrite.c 文件,但没有发现任何有趣的东西,只是也许我写了长双打,但 fread 读双打。writedata.table
0赞 Merijn van Tilborg 4/20/2022
我想我写错了,不是浮点问题,但似乎 fwrite 存储了点后四舍五入两位数的值。我不确定如何防止这种情况发生。
0赞 algae 4/20/2022
不幸的是,对我来说,这似乎是一个更大问题的一部分——特别是当混合了以科学和定点形式编写的数据时。