[这是在一篇文章中提出的多个错误报告/功能请求,但它们不一定孤立地有意义。提前为怪物发布道歉。根据help(data.table)的建议在此处发布。另外,我是R的新手。抱歉,如果我没有遵循下面的代码中的最佳做法。我正在努力。]

1. 6 * 8GB文件上的rbindlist崩溃(我有128GB RAM)

首先,我想报告一下,使用rbindlist append 大data.tables会导致R出现段错误(ubuntu 13.10,打包的R版本3.0.1-3ubuntu1,data.table是从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给出错误消息

我的第二个问题是我需要为我的一种数据类型指定a custom coercion handler,但是失败了:
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 magic(此处简化)(其中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。但是我试图通过将tfile命名为管道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

无论如何,这是一个小技巧。

如果我有愿望 list ,则为简化代码

理想情况下,我将能够执行以下操作:
setClass("Int_Price")
setAs("character", "Int_Price",
    function (from) {
        return(as.integer(gsub("\\.", "", from)))
    }
)

dt <- fread(files, colClasses=list(price="Int_Price"))

然后,我将得到一个很好的带有适当强制数据的长data.table

最佳答案

更新:rbindlist错误已在commit 1100 v1.8.11中修复。从新闻:



如评论中所述,您应该分别提出单独的问题。但是,由于它们的优点如此,最后它们与希望联系在一起,所以可以一口气回答。

1. rbindlist在6 * 8GB文件上崩溃(我有128GB RAM)

请再次运行以更改行:

moves.by.year <- lapply(files, fread)


moves.by.year <- lapply(files, fread, verbose=TRUE)

并发送给我输出。我不认为这是文件的大小,而是有关类型和内容的信息。您说得对,freadrbindlist应该没有问题,将48GB数据加载到128GB盒子上。如您所说,lapply应该返回48GB,然后rbindlist应该创建一个新的48GB单个表。由于96GB data.table尚未 catch R3中的长向量支持,否则> 2 ^ 31行也可以) 。

2. fread可以接受多个文件名吗?

好主意。如您所说,然后fread可以扫描所有6个文件,以检测它们的类型并首先计算行总数。然后直接为6亿行分配一次。这样可以节省不必要的48GB RAM。在开始读取第一个文件之前,它也可能检测到第5个文件或第6个文件中的任何异常(例如),因此在出现问题时可以更快地返回。

我会将其提交为功能请求,然后在此处发布链接。

3. colClasses提供一条错误消息

当键入list时,类型显示在=的左侧,而列名或位置的向量显示在右侧。这个想法要比仅接受向量的colClasses中的read.csv容易。来保存重复的"character"一遍又一遍。我本可以发誓这更好地记录在?fread中,但事实并非如此。我来看一下。

所以,代替
fread(tfile, colClasses=list(date="myDate"))
Error in fread(tfile, colClasses = list(date = "myDate")) :
    Column name 'myDate' in colClasses not found in data

正确的语法是
fread(tfile, colClasses=list(myDate="date"))

给定您要在问题iiuc中继续说的内容,您实际上想要:
fread(tfile, colClasses=list(character="date"))  # just fread accepts list

或者
fread(tfile, colClasses=c("date"="character"))   # both read.csv and fread

这两种方法均应将称为“日期”的列作为字符加载,以便您可以在强制执行之前对其进行操作。如果真的只是约会,那我还是要自动实现这种强制。您提到了numeric的精度,只是为了提醒您integer64也可以直接读取fread

4. fread认为命名管道是空文件

希望假设前面的问题已解决,现在就消失了吗? fread通过内存映射其输入来工作。它可以接受非文件,例如http地址和连接(tbc),为了方便起见,它首先将完整的输入写入ramdisk,以便可以从那里映射输入。 fread快速的原因与首先查看整个输入是紧密相关的。

关于r - 追加多个大数据表使用colClasses和fread的自定义数据强制;命名管道,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21220402/

10-12 23:21