fread/fwrite引入垃圾值。

3

数据文件 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')

揭示了当应该等于时,元素的值为<2.7898250541260385e-311>。是什么导致了垃圾数据的引入? data.dat文件是从C ++文件以以下方式编写的。
    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;

向量v包含写入data.dat的值。我使用的是data.table 1.14.2版本和R 4.1.3。

1个回答

2
显然,在过程中它进行了一些四舍五入操作,而fread将第13个值存储为integer64"integer64"(默认)读取包含大于2^31的整数的列作为bit64 :: integer64类型

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

你能解释一下“这不会防止浮点问题”的意思吗?很奇怪的是,它可以精确地读取到16位数,但无法将其写入文件。例如,write按预期工作,但我不想手动格式化,因此我们才使用像data.table这样的软件包。我的问题也不是写入和重新读取“相同”的数据 - 我正在读取、执行操作然后再次写入。我一直在阅读fwrite.c文件,但没有找到任何有趣的东西,只是可能我写了长双精度数,但fread却读取了双精度数。 - algae
我认为我写错了,不是浮点数问题,而是似乎fwrite将值四舍五入并存储为小数点后两位。我不确定如何防止这种情况发生。 - Merijn van Tilborg
不幸的是,对我来说这似乎是一个更大的问题的一部分 - 特别是当科学和定点形式的数据混合写入时。 - algae

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接