fastaファイルからランダムな200文字のサブストリングを抽出する方法

fastaファイルからランダムな200文字のサブストリングを抽出する方法

ファイルからシーケンスを抽出するために使用できるLinuxコマンドはありますか?たとえば、ファイルには百万行が含まれており、ファイル内のヘッダーに関係なく、200文字の文字列のみをランダムにサンプリングしたいとします。

ランダムとは、200個のシーケンスごとに選択される確率が同じで、選択された部分文字列のいずれも繰り返されないことを意味します。

次のように、fastaファイルから200文字のランダムシーケンス(ヘッダーを考慮しない)を抽出しようとしています。

>NC_001416.1 Enterobacteria phage lambda, complete genome
GGGCGGCGACCTCGCGGGTTTTCGCTATTTATGAAAATTTTCCGGTTTAAGGCGTTTCCGTTCTTCTTCG
TCATAACTTAATGTTTTTATTTAAAATACCCTCTGAAAAGAAAGGAAACGACAGGTGCTGAAAGCGAGGC
TTTTTGGCCTCTGTCGTTTCCTTTCTCTGTTTTTGTCCGTGGAATGAACAATGGAAGTCAACAAAAAGCA
GCTGGCTGACATTTTCGGTGCGAGTATCCGTACCATTCAGAACTGGCAGGAACAGGGAATGCCCGTTCTG
CGAGGCGGTGGCAAGGGTAATGAGGTGCTTTATGACTCTGCCGCCGTCATAAAATGGTATGCCGAAAGGG
ATGCTGAAATTGAGAACGAAAAGCTGCGCCGGGAGGTTGAAGAACTGCGGCAGGCCAGCGAGGCAGATCT
CCAGCCAGGAACTATTGAGTACGAACGCCATCGACTTACGCGTGCGCAGGCCGACGCACAGGAACTGAAG
AATGCCAGAGACTCCGCTGAAGTGGTGGAAACCGCATTCTGTACTTTCGTGCTGTCGCGGATCGCAGGTG
AAATTGCCAGTATTCTCGACGGGCTCCCCCTGTCGGTGCAGCGGCGTTTTCCGGAACTGGAAAACCGACA
TGTTGATTTCCTGAAACGGGATATCATCAAAGCCATGAACAAAGCAGCCGCGCTGGATGAACTGATACCG
GGGTTGCTGAGTGAATATATCGAACAGTCAGGTTAACAGGCTGCGGCATTTTGTCCGCGCCGGGCTTCGC
TCACTGTTCAGGCCGGAGCCACAGACCGCCGTTGAATGGGCGGATGCTAATTACTATCTCCCGAAAGAAT
CCGCATACCAGGAAGGGCGCTGGGAAACACTGCCCTTTCAGCGGGCCATCATGAATGCGATGGGCAGCGA
CTACATCCGTGAGGTGAATGTGGTGAAGTCTGCCCGTGTCGGTTATTCCAAAATGCTGCTGGGTGTTTAT
GCCTACTTTATAGAGCATAAGCAGCGCAACACCCTTATCTGGTTGCCGACGGATGGTGATGCCGAGAACT
TTATGAAAACCCACGTTGAGCCGACTATTCGTGATATTCCGTCGCTGCTGGCGCTGGCCCCGTGGTATGG
CAAAAAGCACCGGGATAACACGCTCACCATGAAGCGTTTCACTAATGGGCGTGGCTTCTGGTGCCTGGGC
GGTAAAGCGGCAAAAAACTACCGTGAAAAGTCGGTGGATGTGGCGGGTTATGATGAACTTGCTGCTTTTG
ATGATGATATTGAACAGGAAGGCTCTCCGACGTTCCTGGGTGACAAGCGTATTGAAGGCTCGGTCTGGCC
AAAGTCCATCCGTGGCTCCACGCCAAAAGTGAGAGGCACCTGTCAGATTGAGCGTGCAGCCAGTGAATCC
CCGCATTTTATGCGTTTTCATGTTGCCTGCCCGCATTGCGGGGAGGAGCAGTATCTTAAATTTGGCGACA
AAGAGACGCCGTTTGGCCTCAAATGGACGCCGGATGACCCCTCCAGCGTGTTTTATCTCTGCGAGCATAA
TGCCTGCGTCATCCGCCAGCAGGAGCTGGACTTTACTGATGCCCGTTATATCTGCGAAAAGACCGGGATC

たとえば、次のシーケンスのサブセットを取得できます。

GCATACCAGGAAGGGCGCTGGGAAACACTGCCCTTTCAGCGGGCCATCATGAATGCGATGGGCAGCGACTACATCCGTGAGGTGAATGTGGTGAAGTCTGCCCGTGTCGGTTATTCCAAAATGCTGCTGGGTGTTTATGCCTACTTTATAGAGCATAAGCAGCGCAACACCCTTATCTGGTTGCCGACGGATGGTGATGC

答え1

任意の200文字の長さのシーケンスを複数素早く選択するには、改行(またはヘッダー)なしでfastaファイルのコピーを保存するのが便利です。

< file.fasta tail -n+2 | tr -d '\n' > newfile

したがって、改行文字を押すか、それを処理するための計算を実行せずに開始文字をランダムに選択します。また、wc -c < file(またはwc -m)を想定してstat -c "%s" file同じ結果を提供するので(通常のコンテンツ、ロケールなどの場合は最初に確認)、statより速く返す方法を使用します。

文字を含むファイルの場合、n使用可能なオプションは、n-200200文字の長い文字列を形成できないため、可能な開始位置から最後の200文字を除外することです。

shuf任意の数値範囲を選択してからの1,n-200組み合わせを選択すると、文字列が抽出されます。headtail-c

n=$(stat -c "%s" newfile)
r=$(shuf -i1-"$((n-200+1))" -n1)
< newfile tail -c+"$r" | head -c200

複数回呼び出すと、さまざまな結果が得られます。独立ランダムに選択します。これは、同一または重複するシーケンスを意味します。

ファイルの同じ場所にないか重複しないなど、異なる基準に従うことを選択するには、同じコマンドでshuf乱数(より高い値)を解析する必要があります。-nまたは、重複を避けるために、既存の値から200に近い新しい値を削除してください。

xをランダムに選択したい場合独立ただし、一意のランダム行シーケンスの作成を開始し、重複項目を削除してからx個を保持することで、headたとえば10個を取得できます。

while true; do sh test.sh; printf "\n"; done | awk '!seen[$0]++' | head

答え2

shufファイル行をランダムに並べ替えます。文字をランダムにサンプリングするには、折りたたみを使用して各文字を並べ替えます。

fold -w 1 file | shuf -n 200 | tr -d '\n'

tr連続して並べ替えてみてください。

ヘッダーをスキップするには:

tail -n+2 | fold -w 1 | shuf -n 200 | tr -d '\n'

答え3

それほど効率的ではありませんが、シーケンスから200バイトのランダムな部分文字列を抽出します。

n=200                                             # number of bytes to extract
num_bytes=$(tail -n+2 file | tr -d '\n' | wc -c)  # remove header and newlines, save nr. of bytes
offset=$(shuf -n1 -i0-$(( num_bytes - n )))       # random offset, between 0 and num_bytes - n
tail -n+2 file | tr -d '\n' |                     # remove header and newlines
  dd count="$n" bs=1 skip="$offset" 2>/dev/null   # extract substring

ヘッダーと改行のないシーケンスのサイズを事前に知っておく必要があるため、入力ファイル(または一時ファイル)への2回のパスが必要です。

答え4

参照されたファイルサイズは100万行、1〜2GBであることが確認されました。改行を削除するためにデータ全体をコピーし、headそれを使用して切り取るためにデータ全体を読み取ることはtail不要なオーバーヘッドのように見えます。

別の方法は、次のようにファイルサイズを決定することです。

szFn="$( stat --format=%s "${Fn}" )"

次に、ファイルに一連のランダムバイトオフセットを生成します。

shuf --input-range=0-$(( szFn - 1 )) -n "${Count}" | sort -n

目的のルックオフセットからファイルを読み取るには、これらのオフセットを繰り返します。

dd status=none bs=1 skip="${Skip}" count="${Lth}" if="${Fn}"

この方法では、約1.5秒でHDDの10.8 GBファイルから任意の単一文字200を検索できます。 (比較すると、wc -lファイルの読み込みに2分28秒かかりました。)改行などを処理するには少し余分なバイトが必要になることがあり、これらの小さな部分だけを切り捨てることができますtr -d '\n'

予想されるファイルサイズのため、いくつかの算術制限を確認しました。 shufは符号なし整数を最大64ビットまで処理でき、Bashはddのように符号付き整数を最大64ビットまで処理できます。

私もshufに関するいくつかの統計を実行しました。各実行には独自のシードが適用され、結果シリーズは偏見がないように見えました。

関連情報