【问题标题】:efficient splitting of fastq files by length按长度有效分割 fastq 文件
【发布时间】:2018-04-11 14:19:17
【问题描述】:

我正在尝试找到一种更省时的方法来按序列长度分割 fastq 文件,即将一个大的 fastq 文件分割成多个只包含相同长度序列的文件。 输入是一个普通的 fastq 文件(每个序列 4 行,实际序列在每个四重奏的第二行),序列长度不同:

@HISEQ:28:H8P69ADXX:1:1101:1462:2036 1:N:0:CTTGTA
NCCATAAAGTAGAAAGCACT
+
#00<FFFFFFFFFIIFIIFF
@HISEQ:28:H8P69ADXX:1:1101:1419:2156 1:N:0:CTTGTA
TGGAGAGAAAGGCAGTTCCTGA
+
BBBFFFFFFFFFFIIIIIIIII
@HISEQ:28:H8P69ADXX:1:1101:1378:2223 1:N:0:CTTGTA
TCCTGTACTGAGCTGCCCCGA
+
BBBFFFFFFFFFFIIIIIIII
@HISEQ:28:H8P69ADXX:1:1101:1585:2081 1:N:0:CTTGTA
AAACCGTTACCATTACTGAGT
+
BBBFFFFFFFFFFIIIIFIII

现在我正在使用 awk 过滤掉特定长度或特定范围内的序列:

awk 'BEGIN {OFS = "\n"} {header = $0 ; getline seq ; getline qheader ; getline qseq ; if (length(seq) == 22) {print header, seq, qheader, qseq}}'

如果我想为每个序列长度创建一个输出文件,我可以使用 for 循环来管理:

for i in {16..33};
awk -v var=$i 'BEGIN {OFS = "\n"} {header = $0 ; getline seq ; getline qheader ; getline qseq ; if (length(seq) == var) {print header, seq, qheader, qseq}}'
done

问题是,虽然它工作正常,但它相当耗时,因为我猜我正在分别检查每个长度的整个文件。另外,我需要事先检查最长和最短的序列。

谁能帮我找到比我的循环更有效的解决方案?如果可能的话,我不必指定范围,而是检查最小和最大长度并自动拆分它们的解决方案。我想在 awk 中做,但我对一切都开放。 谢谢 本尼迪克特

【问题讨论】:

  • 让我想起了这个:stackoverflow.com/questions/3194349/…
  • 不幸的是,我的问题有点不同。我想根据某些标准(序列长度)拆分我的 fastq 文件,而不仅仅是分成一定数量的文件。如果按长度拆分,您最终会得到大小差异很大的文件,因为一些序列长度很少,而另一些则非常丰富。但是感谢您抽出宝贵的时间!

标签: awk fastq


【解决方案1】:

这样的?

$ awk        '{rec=rec sep $0; sep=ORS} 
       !(NR%4){print rec > fn; rec=sep=""} 
       NR%4==2{fn = length($0)".seq"}' file

将生成这3个带有内容的文件

==> 20.seq <==
@HISEQ:28:H8P69ADXX:1:1101:1462:2036 1:N:0:CTTGTA
NCCATAAAGTAGAAAGCACT
+
#00<FFFFFFFFFIIFIIFF

==> 21.seq <==
@HISEQ:28:H8P69ADXX:1:1101:1378:2223 1:N:0:CTTGTA
TCCTGTACTGAGCTGCCCCGA
+
BBBFFFFFFFFFFIIIIIIII
@HISEQ:28:H8P69ADXX:1:1101:1585:2081 1:N:0:CTTGTA
AAACCGTTACCATTACTGAGT
+
BBBFFFFFFFFFFIIIIFIII

==> 22.seq <==
@HISEQ:28:H8P69ADXX:1:1101:1419:2156 1:N:0:CTTGTA
TGGAGAGAAAGGCAGTTCCTGA
+
BBBFFFFFFFFFFIIIIIIIII

由于会有少量这些输出文件,因此无需显式关闭它们。

说明

{rec=rec sep $0; sep=ORS} 逐行构建记录,行间使用 ORS,通过延迟初始化分隔符我们可以消除悬空的第一个分隔符。

!(NR%4)如果行号是4的倍数

{print rec &gt; fn; rec=sep=""}将记录打印到文件并重置记录和分隔符

NR%4==2 如果行号是 2 of 4。

{fn = length($0)".seq"}设置文件名

【讨论】:

  • 非常感谢,很抱歉我花了一段时间才回答。与我的 for 循环相比,你的代码完全符合我的要求,而且只用了不到一半的时间。真正的 5m3.676s 用户 3m25.148s sys 0m8.816s 用于 for 循环,真正的 2m2.489s 用户 0m32.216s sys 0m1.876s 用于您的。
  • 附注:你能解释一下你的代码吗?我试图更好地理解awk。我可以看到我必须更改以获得不同的输出文件名,但除此之外,我很迷茫。
  • 再次感谢您的解释,我想我现在明白你在那里做了什么。
  • 没问题,先付款!
  • 我试图将您的脚本从 fastq 文件改编为 fasta 文件(基本上相同的文件类型,但每个序列只有 2 行而不是 4 行)。我将每次出现的 NR%4 更改为 NR%2,认为这将是一个简单的修复,但我收到以下错误:致命:`>' 重定向的表达式具有空字符串值。其他一切都是一样的。非常感谢任何帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-19
  • 2023-03-17
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多