使用bigmemory将40 GB csv文件读入R中

Shi*_*ion 18 file-io memory-management r

标题在这里非常自我解释,但我将详细说明如下.一些在攻击这个问题我目前的技术是基于中提出的解决方案,这个问题.但是,我面临着一些挑战和限制,所以我想知道是否有人可能会试图解决这个问题.我试图用bigmemory包解决问题,但我遇到了困难.

目前的限制:

  • 使用具有16 GB RAM的Linux服务器
  • 大小为40 GB CSV
  • 行数:67,194,126,114

挑战

  • 需要能够从big.matrix或等效数据结构中随机采样较小的数据集(5-10百万行).
  • 在解析为big.matrix或等效数据结构时,需要能够使用单个NULL实例删除任何行.

到目前为止,结果并不好.显然,我在某些事情上失败了,或许,我只是不太了解大记忆文档.所以,我想我会问这里是否有人使用过

有关此攻击线的任何提示,建议等?或者我应该改变别的吗?如果这个问题与之前的问题非常相似,我很抱歉,但我认为数据规模比以前的问题大20倍.谢谢 !

edd*_*ddi 20

我不知道bigmemory,但为了满足你的挑战,你不需要阅读文件.只需管道一些bash/awk/sed/python /无论处理什么,你都可以做你想要的步骤,即丢弃NULL行并随机选择N行,然后读取.

这是一个使用awk的例子(假设您需要来自具有1M行的文件的100个随机行).

read.csv(pipe('awk -F, \'BEGIN{srand(); m = 100; length = 1000000;}
                       !/NULL/{if (rand() < m/(length - NR + 1)) {
                                 print; m--;
                                 if (m == 0) exit;
                              }}\' filename'
        )) -> df
Run Code Online (Sandbox Code Playgroud)

对我来说,你的意思并不明显NULL,所以我使用它的文字理解,但应该很容易修改它以满足你的需要.


Mar*_*gan 13

这是从大文本文件中采样挑战的纯R解决方案; 它具有绘制正好n的随机样本的额外优点.尽管将行解析为字符向量并且这相对较慢,但效率并不太低.

我们从一个函数签名开始,我们提供一个文件名,我们想要绘制的样本的大小,随机数生成器的种子(以便我们可以重现我们的随机样本!),指示是否有一个头line,然后是一个"reader"函数,我们将用它来将样本解析为R看到的对象,包括...读者函数可能需要的其他参数

fsample <-
    function(fname, n, seed, header=FALSE, ..., reader=read.csv)
{
Run Code Online (Sandbox Code Playgroud)

该函数为随机数生成器播种,打开连接,并读入(可选)标题行

    set.seed(seed)
    con <- file(fname, open="r")
    hdr <- if (header) {
        readLines(con, 1L)
    } else character()
Run Code Online (Sandbox Code Playgroud)

下一步是读入一大块n行,初始化所看到的总行数的计数器

    buf <- readLines(con, n)
    n_tot <- length(buf)
Run Code Online (Sandbox Code Playgroud)

继续读取n行的块,在没有进一步输入时停止

    repeat {
        txt <- readLines(con, n)
        if ((n_txt <- length(txt)) == 0L)
            break
Run Code Online (Sandbox Code Playgroud)

对于每个块,绘制一个n_keep行样本,其行数与当前块中总行数的比例成比例.这可确保在文件上均匀采样行.如果没有要保留的行,请移动到下一个块.

        n_tot <- n_tot + n_txt
        n_keep <- rbinom(1, n_txt, n_txt / n_tot)
        if (n_keep == 0L)
            next
Run Code Online (Sandbox Code Playgroud)

选择要保留的行和要替换的行,然后更新缓冲区

        keep <- sample(n_txt, n_keep)
        drop <- sample(n, n_keep)
        buf[drop] <- txt[keep]
    }
Run Code Online (Sandbox Code Playgroud)

完成数据输入后,我们使用阅读器解析结果并返回结果

    reader(textConnection(c(hdr, buf), header=header, ...)
}
Run Code Online (Sandbox Code Playgroud)

通过使用readBin和搜索Simon Urbanek在R-devel 邮件列表中建议的换行符,可以提高解决方案的效率,但有点复杂.这是完整的解决方案

fsample <-
    function(fname, n, seed, header=FALSE, ..., reader = read.csv)
{
    set.seed(seed)
    con <- file(fname, open="r")
    hdr <- if (header) {
        readLines(con, 1L)
    } else character()

    buf <- readLines(con, n)
    n_tot <- length(buf)

    repeat {
        txt <- readLines(con, n)
        if ((n_txt <- length(txt)) == 0L)
            break

        n_tot <- n_tot + n_txt
        n_keep <- rbinom(1, n_txt, n_txt / n_tot)
        if (n_keep == 0L)
            next

        keep <- sample(n_txt, n_keep)
        drop <- sample(n, n_keep)
        buf[drop] <- txt[keep]
    }

    reader(textConnection(c(hdr, buf)), header=header, ...)
}
Run Code Online (Sandbox Code Playgroud)