使用命名的colClasses在没有表头的情况下(例如没有col.names),如何使用R的data.table fread函数?

4

更新(2016年6月)

在data.table 1.9.6上添加了col.names,所以问题已经解决,每个人都非常高兴 :) 我想现在我可以将所有的read.csv调用转换为fread调用,而不必担心破坏问题。

原始问题

使用data.table 1.9.4

由于我们注意到巨大的性能提升,我正在将read.csv调用导入到fread中。大多数问题我都可以处理,但我到达了一个无头绪的地步,想知道是否有任何优雅的解决方案。

我的问题是我有命名的colClasses,但输入没有标题(它是grep函数),这里有一个愚蠢的例子来理解:

males.students <- read.csv(pipe("grep Male students.csv"), 
                           col.names=c("id", "name", "gender"), 
                           colClasses=(id="numeric"))

现在在fread中,我仍然想使用命名为colClasses的内容,但是我没有列名,因此只能使用

males.students <- fread("grep Male students.csv"), 
                        colClasses=(id="numeric"))

出现错误:

在colClasses [[1]]中未找到列名为'id'的列

我该如何解决?是否有计划添加列名?


既然你知道这是第一列,你可以直接使用列号。colClasses=list(numeric=1)) - shadow
请尝试同时使用 select 参数。 - Rich Scriven
@shadow 这显然是一个极为简化的例子 - 实际的 CSV 有 40 列,我正在为其中的 19 列设置 colClasses,并且我真的不认为使用列号是合理的。您希望您的系统具有鲁棒性,并允许进行更改,而不会在没有弄清原因的情况下使数据类型神秘地更改。 - ben.pere
只是好奇,为什么您需要设置19个列类?它们是哪些类?如果数据干净,它们应该正确读入。 - Rich Scriven
@RichardScriven select只允许按名称/索引选择要返回的列,而不能更改它们的名称。我需要设置colClasses,因为有些列看起来像数字,但实际上只有作为字符才有意义,例如在财务中,交易订单ID“00000000123”和“00000123”是不同的订单,这仅表示为字符而不是数字。 - ben.pere
2个回答

3
在命令行中添加名称:
fread('echo "id,name,gender"; grep Male students.csv', colClasses = c(id='numeric'))

2
这种方法不适用于大文件的规模。 - smci
@smci 嗯,需要扩展什么吗?在现有的 grep 上添加 echo 不会增加任何额外负担。 - eddi
echo+grep 正在使用命令行创建一个可能非常大且会耗尽内存的临时文件。如果 students.csv 有 10M 行呢? - smci
@smci OP已经在使用grep过滤原始文件之前进行了工作,因此echo不会增加任何开销,也不会有任何内存惩罚。如果您无法读取已过滤的文件,则肯定无法读取原始文件。 - eddi

0
回答原问题,如果问题是 grep 删除了标题,你可以使用 awk 来代替,打印第一行和任何包含 "Male" 的行:
fread("awk 'NR==1 || /Male/' students.csv"), colClasses=(id="numeric"))

这可能对仍在使用旧版本的data.table的人有所帮助。

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