ファイルのサブセットをランダムにサンプリングする方法

ファイルのサブセットをランダムにサンプリングする方法

ファイルのサブセットをサンプリングするために使用できるLinuxコマンドはありますか?たとえば、ファイルには百万行が含まれており、ファイル内の千行だけをランダムにサンプリングしたいとします。

ランダムとは、すべての行が選択される確率が同じで、選択された行のいずれも重複しないことを意味します。

headtailファイルのサブセットを選択できますが、ランダムに選択することはできません。私はこれを行うためにいつでもPythonスクリプトを書くことができることを知っていますが、それに対するコマンドがあるかどうか疑問に思います。

答え1

コマンドshuf(coreutilsの一部)で次のことができます。

shuf -n 1000 file

少なくとも今は非古代バージョン(追加)2013年からの約束)、これは適切な場合はリポジトリサンプリングを使用します。つまり、メモリが不足してはならず、高速アルゴリズムを使用していることを意味します。

答え2

お持ちの場合とても大きいファイル(サンプリングの一般的な理由)で、以下を見つけることができます。

  1. shufメモリ不足
  2. $RANDOMファイルが32767行を超えると、正常に使用できません。

「正確に」n本のサンプルラインが必要ない場合あなたはできますサンプリング比このように:

cat input.txt | awk 'BEGIN {srand()} !/^$/ { if (rand() <= .01) print $0}' > sample.txt

これ使用永久メモリ、ファイルの1%をサンプリングします(ファイルの行数がわかっている場合は、この要素を調整してほぼ限られた数の行をサンプリングできます)。どんなサイズにも適していますしかし、そのファイル〜しないだろう返す精密行数は統計的比率にすぎません。

注:コードソース:https://stackoverflow.com/questions/692312/randomly-pick-lines-from-a-file-without-slurping-it-with-unix

答え3

@Txangelの確率ソリューションに似ていますが、100倍高速です。

perl -ne 'print if (rand() < .01)' huge_file.csv > sample.csv

高性能で正確なサンプルサイズが必要で、ファイルの末尾にサンプル間隔を許可したい場合は、次のようにできます(1mラインファイルから1000ラインサンプリング)。

perl -ne 'print if (rand() < .0012)' huge_file.csv | head -1000 > sample.csv

..または実際には、2番目の例の方法を代わりに接続してくださいhead

答え4

ヘッダー行を保存し、サンプルがファイルのおおよその割合になる可能性があるときにawkを使用するのが好きです。非常に大きなファイルの場合:

awk 'BEGIN {srand()} !/^$/ { if (rand() <= .01 || FNR==1) print > "data-sample.txt"}' data.txt

関連情報