【问题标题】:Preventing column-class inference in fread()防止 fread() 中的列类推断
【发布时间】:2015-06-12 11:54:07
【问题描述】:

fread 有没有办法模仿read.table 的行为,其中变量的class 由读入的数据设置。

我在主要数据下方有几个 cmets 的数字数据。当我使用fread 读取数据时,这些列将转换为字符。但是,通过在 read.table 中设置nrow,我可以停止这种行为。这在 fread 中是否可能。 (我不希望更改原始数据或制作修改后的副本)。谢谢

一个例子

d <- data.frame(x=c(1:100, NA, NA, "fff"), y=c(1:100, NA,NA,NA)) 
write.csv(d, "test.csv",  row.names=F)

in_d <- read.csv("test.csv", nrow=100, header=T)
in_dt <- data.table::fread("test.csv", nrow=100)

哪个产生

> str(in_d)
'data.frame':   100 obs. of  2 variables:
 $ x: int  1 2 3 4 5 6 7 8 9 10 ...
 $ y: int  1 2 3 4 5 6 7 8 9 10 ...
> str(in_dt)
Classes ‘data.table’ and 'data.frame':  100 obs. of  2 variables:
 $ x: chr  "1" "2" "3" "4" ...
 $ y: int  1 2 3 4 5 6 7 8 9 10 ...
 - attr(*, ".internal.selfref")=<externalptr>

作为一种解决方法,我认为我可以使用read.table 在一行中阅读,获取课程并设置colClasses,但我误解了。

cl <- read.csv("test.csv", nrow=1,  header=T)
cols <- unname(sapply(cl, class))
in_dt <- data.table::fread("test.csv", nrow=100, colClasses=cols)
str(in_dt)

使用Windows8.1 R 版本 3.1.2 (2014-10-31) 平台:x86_64-w64-mingw32/x64(64位)

【问题讨论】:

  • 听起来像是一个合理的计划,但我实际上阅读了帮助页面:“如果 colClasses 请求它,fread 只会将列提升为更高的类型。它不会将列降级为更低的类型,因为NAs 会导致。如果你真的需要数据丢失,你必须自己强制这些列。似乎即使将读取限制为 5 行也失败了。我想我记得 colClasses 机制是最近才添加的,所以也许你应该提交一个功能请求。马修和阿伦经常很随和。
  • 肯定必须有一个 DT 策略来强制所有列为数字?将.SDcols 设置为适当的向量,如下所示:DT[, .SD := lapply(.SDcols, as.numeric), .SDcols=vec]。我不是 DT 用户,但我确信有某种最小输入方法,我怀疑你可以在 SO 答案中找到它的说明。
  • @BondedDust;我也不是 DT 用户,它只是 read.table 与我的数据相比 fread 存在(更严重的)问题。生病看看SO。谢谢
  • 听着,别再反抗你的头衔了。这不是关于“使用 nrows”。将字符串写入整数列是故意写入有缺陷的 csv。您的问题是 “我可以防止 data.table 的 fread 列类推断被数据中的尾随字符串注释行覆盖吗?” 您知道注释行应该以评论字符(如#)。当我们将其添加到您的评论文本中时,我们会使用read.csv(但不是fread)得到正确的行为。是的,fread 可以进行增强。同时需要一种解决方法。
  • 感谢您的意见。 . "Writing out a string to an integer column is intentionally writing a defective csv." - 这是一个mwe 以反映我拥有的一些数据,因此没有评论。如果我将# 添加到文件中,它不会反映我拥有的数据。顺便说一句,我没有恢复。

标签: r data.table read.table


【解决方案1】:

选项 1:使用系统命令

fread() 允许在其第一个参数中使用系统命令。我们可以使用它来删除文件第一列中的引号。

indt <- data.table::fread("cat test.csv | tr -d '\"'", nrows = 100)
str(indt)
# Classes ‘data.table’ and 'data.frame':    100 obs. of  2 variables:
#  $ x: int  1 2 3 4 5 6 7 8 9 10 ...
#  $ y: int  1 2 3 4 5 6 7 8 9 10 ...
#  - attr(*, ".internal.selfref")=<externalptr> 

系统命令cat test.csv | tr -d '\"'解释:

  • cat test.csv 读取文件到标准输出
  • | 是一个管道,使用上一个命令的输出作为下一个命令的输入
  • tr -d '\"' 从当前输入中删除 (-d) 所有出现的双引号 ('\"')

选项2:阅读后强制

由于选项 1 似乎不适用于您的系统,另一种可能性是像您一样读取文件,但将 x 列转换为 type.convert()

library(data.table)
indt2 <- fread("test.csv", nrows = 100)[, x := type.convert(x)]
str(indt2)
# Classes ‘data.table’ and 'data.frame':    100 obs. of  2 variables:
#  $ x: int  1 2 3 4 5 6 7 8 9 10 ...
#  $ y: int  1 2 3 4 5 6 7 8 9 10 ...
#  - attr(*, ".internal.selfref")=<externalptr> 

旁注:我通常更喜欢使用type.convert() 而不是as.numeric() 以避免在某些情况下触发“强制引入的NAs”警告。例如,

x <- c("1", "4", "NA", "6")
as.numeric(x)
# [1]  1  4 NA  6
# Warning message:
# NAs introduced by coercion 
type.convert(x)
# [1]  1  4 NA  6

当然你也可以使用as.numeric()


注意:此答案假定data.table dev v1.9.5

【讨论】:

  • 谢谢理查德,但是,这会在我的系统上引发错误。我正在使用 Windows 8.1
  • 感谢您提供额外信息。我已经安装了开发版本,但在 Windows 上出现了同样的错误(有效,在 linux 上有有用的警告)。请您解释一下系统调用命令。
  • @user2957945 - 好的,很高兴知道。我添加了第二个应该足够有效的选项
  • 呵呵... 使用系统调用的错误可能已经说得太早了。实际上看起来 fread 自开发版本以来根本不起作用。生病从 cranand 加载,看看它是否修复。再次感谢您的帮助。
  • @user2957945 - 重做时,使用新的 R 会话以避免与其他对象发生冲突
【解决方案2】:

好的,客户 abusing CSV format 有意将尾随字符串行写入整数列,但没有以 comment.char (#) 开头的行。

然后您以某种方式期望您可以覆盖 fread() 的类型推断以将它们读取为整数,方法是使用 nrow 尝试将其限制为仅查看整数行。 read.csv(..., nrow) 会接受这一点,但是 fread() 总是使用所有行进行类型推断(不仅仅是 nrow, skip, header 指定的行),即使它们以 comment.char 开头(这是一个错误)。

  1. 听起来像是在滥用 CSV。您的评论行应以# 开头
  2. 是的,fread() 需要修复/增强以忽略注释行以进行类型推断。
  3. 目前,您可以通过对读入的数据表进行后处理来解决 fread() 问题。
  4. 是否应该更改 fread() 以支持您想要的行为是有争议的:使用 nrows 来限制暴露于类型推断的内容。它可能会修复您的(非常独特的)案例并打破其他案例。

我不明白为什么您(编辑:客户)不能将您的 cmets 写入单独的 .txt/README/data-dictionary 文件以伴随 .csv。使用单独的数据字典文件的做法非常成熟。 我从未见过有人对 CSV 文件执行此操作。至少将 cmets 移动到页眉,而不是页脚。

【讨论】:

  • csv 没有多行标题。它在文件底部有不需要的东西
  • 好的,然后是尾随(字符串)注释行,没有任何前导“#”。为什么不手动将它们附加到 write.csv?
  • 这不是我的问题,但我猜 OP 已经有了该文件,只是使用 write.csv() 创建了一个示例。
  • 重新更新您的更新:1) 数据已提供给我,因此未对其进行评论。 3)是的,将这些额外信息添加到底部没有帮助,但我经常收到这样的数据,客户在主要数据下方添加小摘要或文本(不幸的是,这对我来说不是一个独特的案例)
  • 我认为你的论点有点超出了问题的范围。难道我们不能规定这是一种不好的数据格式,然后询问OP如何处理它吗? (我知道这里有一个 reductio ad absurdum,例如“我的客户正在将他们的数据作为屏幕截图嵌入到 .mp4 文件中:我如何使用fread 来阅读它?”,但是这种情况似乎远非如此。)
猜你喜欢
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 2019-07-24
  • 1970-01-01
  • 2021-10-14
  • 2016-11-07
  • 2021-05-14
相关资源
最近更新 更多