这篇文章涉及多个bug报告/功能请求,但它们在分离后并不一定有意义。事先抱歉这篇巨大的文章。按照help(data.table)的建议在此发布。另外,我是R的新手,如果我在下面的代码中没有遵循最佳实践,请谅解。我正在努力学习。
1. rbindlist
在6*8GB文件上崩溃(我的内存为128GB)
首先,我想报告一下使用rbindlist将大型数据表附加到数据表会导致R崩溃(ubuntu 13.10,封装的R版本3.0.1-3ubuntu1,数据表从CRAN中的R中安装)。机器有128 GiB的RAM,因此,考虑到数据的大小,我不应该耗尽内存。
我的代码:
append.tables <- function(files) {
moves.by.year <- lapply(files, fread)
move <- rbindlist(moves.by.year)
rm(moves.by.year)
move[,week_end := as.Date(as.character(week_end), format="%Y%m%d")]
return(move)
}
崩溃信息:
append.tables crashes with this:
> system.time(move <- append.tables(files))
*** caught segfault ***
address 0x7f8e88dc1d10, cause 'memory not mapped'
Traceback:
1: rbindlist(moves.by.year)
2: append.tables(files)
3: system.time(move <- append.tables(files))
这里有6个文件,每个文件大约有8 GiB或1亿行,包含8个变量,使用制表符分隔。
2. fread
能否接受多个文件名?
无论如何,在这种情况下,我认为更好的方法是允许 fread 接受作为文件名向量的文件:
files <- c("my", "files", "to be", "appended")
dt <- fread(files)
在内部实现时,您可以比使用R语言时需要同时保留所有这些对象更节省内存。
3. colClasses
会报错
我的第二个问题是,我需要为其中一种数据类型指定自定义转换处理程序,但该操作失败:
dt <- fread(tfile, colClasses=list(date="myDate"))
Error in fread(tfile, colClasses = list(date = "myDate")) :
Column name 'myDate' in colClasses not found in data
是的,在日期方面,简单地写:
dt[,date := as.Date(as.character(date), format="%Y%m%d")]
工作正常。
然而,我有一个不同的用例,那就是在将字符转换为整数之前从其中一个数据列中删除小数点。这里的精度非常重要(因此我们需要使用整数类型),从 double 类型强制转换为整数会导致数据丢失。
现在,我可以通过一些 system() 调用来迂回处理此问题,将文件追加并通过一些 sed 魔法来处理它们(在这里被简化)(其中 tfile 是另一个临时文件):
if (has_header) {
tfile2 <- tempfile()
system(paste("echo fakeline >>", tfile2))
system(paste("head -q -n1", files[[1]], ">>", tfile2))
system(paste("tail -q -n+2", tfile2, paste(files, collapse=" "),
" | sed 's/\\.//' >>", tfile), wait=wait)
unlink(tfile2)
} else {
system(paste("cat", paste(files, collapse=" "), ">>", tfile), wait=wait)
}
但这需要额外的读/写循环。我有4 TiB的数据要处理,这需要大量的额外读写(不是全部放到一个data.table中,而是分成约1000个)。
4. fread
认为命名管道是空文件
通常我会设置wait=TRUE。但我想尝试通过使用命名管道system('mkfifo', tfile)
、设置wait=FALSE,并运行fread(tfile)来避免额外的读写循环。然而,fread抱怨管道是一个空文件:
system(paste("tail -q -n+2", tfile2, paste(files, collapse=" "),
" | sed 's/\\.//' >>", tfile), wait=FALSE)
move <- fread(tfile)
Error in fread(tfile) : File is empty: /tmp/RtmpbxNI1L/file78a678dc1999
无论如何,这都有点像是一个黑客攻击。
如果我有愿望清单,代码将更简化
理想情况下,我希望能够像这样做:
setClass("Int_Price")
setAs("character", "Int_Price",
function (from) {
return(as.integer(gsub("\\.", "", from)))
}
)
dt <- fread(files, colClasses=list(price="Int_Price"))
然后我会得到一个很好的、经过适当强制转换的数据表 data.table
。