18

タイトルはここでかなり自明ですが、次のように詳しく説明します。この問題に対処するための現在のテクニックのいくつかは、この質問で提示されたソリューションに基づいています。しかし、私はいくつかの課題と制約に直面しているので、誰かがこの問題に挑戦しようとするのではないかと思っていました. bigmemoryパッケージを使用して問題を解決しようとしていますが、問題が発生しています。

現在の制約:

  • 16 GB の RAM を搭載した Linux サーバーを使用する
  • 40 GB CSV のサイズ
  • 行数: 67,194,126,114

課題

  • big.matrix または同等のデータ構造から小さなデータセット (500 万から 1000 万行) をランダムにサンプリングできる必要があります。
  • big.matrix または同等のデータ構造に解析する際に、NULL の単一インスタンスを含む行を削除できる必要があります。

これまでのところ、結果は良くありません。明らかに、私は何かで失敗しているか、bigmemory のドキュメントを十分に理解していないだけかもしれません。だから、私は誰かが使用したかどうかを確認するためにここに尋ねると思いました

この一連の攻撃に関するヒントやアドバイスはありますか? それとも別のものに変更する必要がありますか?この質問が以前の質問と非常に似ている場合は申し訳ありませんが、データの規模で言えば、以前の質問よりも約 20 倍大きいと思いました。ありがとう !

4

2 に答える 2

21

についてはわかりませんがbigmemory、課題を満たすためにファイルを読み込む必要はありません。単に bash/awk/sed/python/whatever 処理をパイプして、必要な手順を実行します。つまり、NULL行を破棄してランダムに選択しますN行を読み込んでから、それを読み込んでください。

awk を使用した例を次に示します (100 万行のファイルから 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(textConnection(c(hdr, buf), header=header, ...)
}

R-develメーリングリストreadBinでSimon 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 に答える