18

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

当前约束:

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

挑战

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

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

关于这条攻击线的任何提示、建议等?还是我应该换成别的东西?如果这个问题与之前的问题非常相似,我深表歉意,但我认为数据规模比之前的问题大 20 倍左右。谢谢 !

4

2 回答 2

21

我不知道bigmemory,但为了满足您的挑战,您不需要读取文件。只需管道一些 bash/awk/sed/python/whatever 处理来执行您想要的步骤,即抛出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

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

于 2013-04-03T21:15:45.063 回答
14

这是从大型文本文件中采样挑战的纯 R 解决方案;它还有一个额外的优点,就是随机抽取 n 个样本。尽管将行解析为字符向量并且这相对较慢,但它的效率并不算太低。

我们从一个函数签名开始,我们提供一个文件名、我们想要绘制的样本的大小、一个随机数生成器的种子(这样我们就可以重现我们的随机样本!),以及是否有标题的指示行,然后是一个“阅读器”函数,我们将使用该函数将样本解析为 R 看到的对象,包括...阅读器函数可能需要的其他参数

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()

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

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

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

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

对于每个块,绘制线条样本,n_keep线条数与当前块中总线条的比例成正比。这可确保在文件中对行进行均匀采样。如果没有要保留的行,则移至下一个块。

        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 解析结果并返回结果

    reader(textConnection(c(hdr, buf), header=header, ...)
}

通过使用和搜索 R-devel邮件列表中readBinSimon Urbanek 所建议的换行符,该解决方案可以变得更高效,但更复杂一些。这是完整的解决方案

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, ...)
}
于 2013-08-16T20:58:00.573 回答