Coreutilsのshufを使ってみた

1行1エントリの巨大なデータから数千行サンプリングして小さいデータを作りたい、という問題が起きた。overlastさんにCoreutilsのshufを紹介していただいたので使ってみた。これは便利。

参考:
http://www.gnu.org/software/coreutils/
http://ftp.gnu.org/gnu/coreutils/


Coreutilsのshufはデータを行単位でシャッフルしてくれる。なので

$$ shuf large_data.txt > large_data.txt.shuf
$$ head -1000 large_data.txt.shuf > data.txt

などとすればサンプリングしたデータが得られる。

また、ファイルAとファイルBが行単位でペアになっていて、ファイルAからサンプリングした行に対応するファイルBの行を取得したい場合がある。例えば対訳テキストで

$$ cat large_test.src
I wonder Gibbs is "HIKIKOMORI".
Pay for performance!
A lion is dangerous animal.
...

$$ cat large_test.dst
ギプスはヒキコモリじゃないだろうか。
パフォーマンスに対して給与を支払ってください!
ライオンは危険な動物だ。
...

というものを想像してもらうと良い。こういうデータでlarge_test.srcの2行目「Pay for performance!」がサンプリングされたときは、large_test.dstから対応する「パフォーマンスに対して給与を支払ってください!」をサンプリングしたい。

この場合、以下のようにすると特定のファイル内容をシードにした乱数でシャッフルされるので。同じファイルをシードにすれば常に対応する行がサンプリングできる。

$$ shuf --random-source=seed.txt 
   large_test.src > large_test.src.shuf
$$ head -1000 large_test.src.shuf > test.src
$$ shuf --random-source=seed.txt 
   large_test.dst > large_test.dst.shuf
$$ head -1000 large_test.dst.shuf > test.dst