【问题标题】:sorting a multiFASTA file by DNA length按 DNA 长度排序 multiFASTA 文件
【发布时间】:2026-01-04 21:00:02
【问题描述】:

我正在尝试按长度对 multiFASTA 文件进行排序。我已经弄清楚了字母排序,但我似乎无法获得数字排序。输出应该是一个排序的 multiFASTA 文件。这是另一个程序的选项。这是代码。

sub sort {
my $length;
my $key;
my $id;
my %seqs;
my $seq;
my $action = shift;
my $match = $opts{$action};
$match =~ /[l|id]/ || die "not the right parameters\n";
my $in = Bio::SeqIO->new(-file=>"$filename", -format=>'fasta');
    while(my $seqobj = $in->next_seq()){
        my $id = $seqobj->display_id();
        my $length=$seqobj->length();
        #$seq =~s/.{1,60}\K/\n/sg;
        $seqs{$id} = $seqobj, unless $match eq 'l';
        $seqs{$length}=$seqobj, unless $match eq 'id';
    }
    if($match eq 'id'){
        foreach my $id (sort keys %seqs) {
             printf ">%-9s \n%-s\n", $id, $seqs{$id}->seq;
        }
    }
    elsif($match eq 'l'){
        foreach my $length ( sort keys %seqs){
             printf "%-10s\n%-s\n",$length, $seqs{$length}->seq;
        }
    }
}

【问题讨论】:

    标签: sorting bioinformatics bioperl


    【解决方案1】:

    您可以使用pyfaidx 或查看jim hester repos。但正如@pierre 上面所说的,你应该问你关于生物之星的问题。关于biostars的答案可以在here找到。

    【讨论】:

      【解决方案2】:

      单行:使用 awk 到 linearize。第二个 awk 添加包含长度的列,对此列进行排序,删除列,恢复 fasta 序列。

      awk '/^>/ {printf("%s%s\t",(N>0?"\n":""),$0);N++;next;} {printf("%s",$0);} END {printf("\n");}'  input.fa  |\
      awk -F '\t' '{printf("%d\t%s\n",length($2),$0);}' |\
      sort -t $'\t' -k1,1n |\
      cut -f 2- |\
      tr "\t" "\n"
      

      PS:对于生物信息学的问题,你应该使用https://www.biostars.org/,或者https://bioinformatics.stackexchange.com/等...

      【讨论】:

        【解决方案3】:

        要按数字排序,您必须提供比较子例程:

        sort { $a <=> $b } keys %seqs
        

        您确定没有两个序列可以具有相同的长度吗? $seqs{$length}=$seqobj 覆盖之前存储的值。

        【讨论】:

        • 这也是我遇到的问题。它只显示 3 个序列。我不知道它会替换该值,因为按字母顺序排序很好,但现在我明白这是因为每个 id 都不同。
        • @JefferyRosario:没错。您可以使用哈希的哈希值并填充$seqs{$length}{$id} = $seqobj,然后您需要两个嵌套的 for 循环来迭代它们,一个按长度排序,内部一个按 id 排序。
        • 非常感谢。我想到了。我也不需要这行代码:sort { $a $b } keys %seqs.
        • 这是我更新的按长度排序的代码: elsif($match eq 'l'){ foreach my $length(sort keys %seqs){ foreach my $id (keys %{ $seqs {$length}}) { printf "%-10s\n%-s\n" ,$id, $seqs{$length}{$id}->seq;
        • @JefferyRosario:但它在 3 之前排序 20。