来自 data.table 包的 fread 无法读取小数字
Posted
技术标签:
【中文标题】来自 data.table 包的 fread 无法读取小数字【英文标题】:fread from data.table package can't read small numbers 【发布时间】:2014-02-13 10:54:25 【问题描述】:我正在使用来自data.table
的fread()
有效地将大型矩形CSV 文件读入R
,这些文件都是double
(并且只有double
)值——没有丢失元素。
但是,如果我的科学记数法中的数字非常小,它会转换为字符,从而破坏整个阅读过程。这是错误信息(例如,每个小数字有多个):
16:在 fread("SomeCSVFile") 中: 碰撞列 560 以在数据行 16799 上键入字符,字段包含“-2.1412168512924677E-308”。将此列中先前读取的值从整数或数字强制转换回可能不是无损的字符;例如,如果 '00' 和 '000' 在它们现在只是 '0' 之前出现,并且对 ',,' 和 ',NA,' 的处理也可能存在不一致(如果它们在颠簸之前出现在此列中)。如果这很重要,请重新运行并将此列的“colClasses”设置为“字符”。请注意,列类型检测使用前 5 行、中间 5 行和最后 5 行,因此希望此消息应该很少见。如果向 datatable-help 报告,请重新运行并包含 verbose=TRUE 的输出。
我希望函数将它们设置为零或将它们截断为可能的最小值(两者都可以)。
【问题讨论】:
通过提供一些重现问题的示例数据,可以极大地改善这个问题。 真正的问题是什么?你对这些小价值有什么实际用处吗?谁首先允许 Excel 工作表生成它们?如果您无论如何要将它们设置为零,只需将它们读入然后matrix[is.character(matrix)]<-numeric(0)
@CarlWitthoft 我不使用 Excel,但感谢您的解决方案。
糟糕,我假设所有csv
都是从 Excel 的邪恶坑中产生的。
当我尝试输入具有非常小的指数的数字时,它们被读取为 0 - 您需要为您的设置添加一个可重现的示例 + 操作系统/包详细信息 - 因为这不是一个好问题
【参考方案1】:
为了重现这一点,我将此内容放在一个文本文件中:
x
1
1
1
1
1
1e-309
然后我打电话给fread("that file.txt")
。
R能存储的最小正数的大小是
format(.Machine$double.xmin, digits = 22)
## [1] "2.2250738585072013828e-308"
您的数据文件包含值-2.1412168512924677E-308
,小于此限制。为了防止 R 将该值视为零,data.table
包已将该列转换为字符串。这样可以防止数据精度丢失。
如果您需要使用此大小的值,请使用Rmpfr
包以更精确地存储数字。将它们作为字符导入(使用colClasses
;请参阅该数据表警告文本)。然后使用
library(Rmpfr)
mpfr("-2.1412168512924677E-308")
## 1 'mpfr' number of precision 70 bits
## [1] -2.1412168512924676999992e-308
正如 Ben Bolker 在 cmets 中所说的那样。如果您不关心微小的数字,而只想将它们视为零,则将该列导入为字符,然后使用as.numeric
。
the_data <- fread("the file.txt", colClasses = "character")
the_data$DodgyColumn <- as.numeric(the_data$DodgyColumn)
【讨论】:
但这意味着如果我的矩阵不是统一的数字,我什至不能再使用fread
。我如何从实际的角度解决这个问题,知道-2.14...E-308
和-2.225..E-308
之间的区别对我的用例来说没有任何意义(即让它四舍五入到零或合理的值)。
你可以使用fread
;你只需要指定colClasses
参数。重新阅读该警告文本。
您是否真的重现了 OP 的问题(如果是,您能否在您的答案中添加一个可重现的示例)?他们所描述的对我来说不会发生 - 小数字被读为 0。
@eddi 已按要求更新答案。使前 5 个数字合理,因此该列被视为数字,然后提供一个非常小的数字。
来自 1.8.11 新闻:“fread("1.46761e-313\n")
检测到 ERANGE 错误,因此读取为字符。现在读取为数字,但带有详细警告。感谢 Heather Turner 的详细报告,@987654321 @。”以上是关于来自 data.table 包的 fread 无法读取小数字的主要内容,如果未能解决你的问题,请参考以下文章
data.table 的 fread() 给出不需要的下载消息