【问题标题】:Find the number of matching two characters in a string in Perl在 Perl 中查找字符串中匹配的两个字符的数量
【发布时间】:2011-11-18 14:57:33
【问题描述】:

Perl 中有没有方法(不是BioPerl)来查找每两个连续字母的个数。

即,AA, AC, AG, AT, CC, CA, ... 的数量,如下所示:

$sequence = 'AACGTACTGACGTACTGGTTGGTACGA'

PS:我们可以手动使用正则表达式,即$GC=($sequence=~s/GC/GC/g),返回序列中GC的个数。

我需要一种自动化的通用方式。

【问题讨论】:

  • 匹配项是否需要重叠 - 例如,上面的第 2 和第 3 个字符是否算作“AC”?
  • 不只有两个连续的字母
  • @AWRAM A 和 C 在第 2 位和第 3 位是连续的。你的意思是说AACG只能算AA和CG?
  • 由于我不熟悉生物:二核苷酸由此字符串中的每两个字符表示,或者存在现有二核苷酸列表且字符串包含 1 或 3+ 个长原子字符组的序列?跨度>
  • 是的,从一开始我们就有 AA 和 AC CG 和 GT 没关系..

标签: string perl pattern-matching match bioperl


【解决方案1】:

你让我困惑了一段时间,但我认为你想计算给定字符串中的二核苷酸。

代码:

my @dinucs = qw(AA AC AG CC CA CG);
my %count;
my $sequence = 'AACGTACTGACGTACTGGTTGGTACGA';

for my $dinuc (@dinucs) {
    $count{$dinuc} = ($sequence =~ s/\Q$dinuc\E/$dinuc/g);
}

Data::Dumper 的输出:

$VAR1 = {
          "AC" => 5,
          "CC" => "",
          "AG" => "",
          "AA" => 1,
          "CG" => 3,
          "CA" => ""
        };

【讨论】:

  • 这个问题没有说清楚,但我认为重叠是这个应用程序中的一个问题。该字符串应一次处理两个。
  • @Zaid 这是基于他自己的解决方案,他声称这对他有用。
  • 这可能意味着他自己的解决方案没有给他正确的答案:)
  • @pavel 这是我认为他的问题中唯一明确的部分:他可以手动完成,但他想要一个自动化的和通用解决方案。
  • 你也可以使用$count{$dinuc} = $sequence =~ tr/$dinuc/$dinuc/;
【解决方案2】:

接近TLP's answer,但没有替代:

my $sequence = 'AACGTACTGACGTACTGGTTGGTACGA';
my @dinucs = qw(AA AC AG AT CC CG);
my %count = map{$_ => 0}@dinucs;

for my $dinuc (@dinucs) {
    while($sequence=~/$dinuc/g) {
        $count{$dinuc}++;
    }
}

基准测试:

my $sequence = 'AACGTACTGACGTACTGGTTGGTACGA';
my @dinucs = qw(AA AC AG AT CC CG);
my %count = map{$_ => 0}@dinucs;

my $count = -3;
my $r = cmpthese($count, {
        'match' => sub {
            for my $dinuc (@dinucs) {
               while($sequence=~/$dinuc/g) {
                    $count{$dinuc}++;
               }
            }
        },
        'substitute' => sub {
            for my $dinuc (@dinucs) {
                $count{$dinuc} = ($sequence =~ s/\Q$dinuc\E/$dinuc/g);
            }
         }
});

输出:

              Rate substitute      Match
Substitute 13897/s         --       -11%
Match      15622/s        12%         --

【讨论】:

    【解决方案3】:

    如果你小心,Regex 可以工作,但有一个使用 substr 的简单解决方案,它会更快、更灵活。

    (截至本文发布时,the regex solution marked as accepted 将无法正确计算重复区域中的二核苷酸,例如 'AAAA...',其中许多是自然发生的序列。

    匹配“AA”后,正则表达式搜索将在第三个字符处继续,跳过中间的“AA”二核苷酸。这不会影响其他二核苷酸,因为如果您在一个位置有“AC”,那么您自然可以保证它不会出现在下一个碱基中。问题中给出的特定序列不会出现这个问题,因为没有碱基连续出现 3 次。)

    我建议的方法更灵活,它可以计算任意长度的单词;将正则表达式方法扩展到更长的单词很复杂,因为您必须使用正则表达式做更多的体操才能获得准确的计数。

    sub substrWise {
        my ($seq, $wordLength) = @_;
    
        my $cnt = {};
    
        my $w;
        for my $i (0 .. length($seq) - $wordLength) {
            $w = substr($seq, $i, $wordLength);
            $cnt->{$w}++;
        }
    
        return $cnt;
    }
    
    sub regexWise {
        my ($seq, $dinucs) = @_;
    
        my $cnt = {};
        for my $d (@$dinucs) {
            if (substr($d, 0,1) eq substr($d, 1,1) ) {
                my $n = substr($d, 0,1);
                $cnt->{$d} = ($seq =~ s/$n(?=$n)/$n/g); # use look-ahead
            } else {
                $cnt->{$d} = ($seq =~ s/$d/$d/g);
            }
        }
    
        return $cnt;
    }
    
    
    my @dinucs = qw(AA AC AG AT CA CC CG CT GA GC GG GT TA TC TG TT);
    
    my $sequence = 'AACGTACTGACGTACTGGTTGGTACGA';
    
    use Test::More tests => 1;
    my $rWise = regexWise($sequence, \@dinucs);
    my $sWise = substrWise($sequence, 2);
    $sWise->{$_} //= '' for @dinucs; # substrWise will not create keys for words not found
    # this seems like desirable behavior IMO,
    # but i'm adding '' to show that the counts match
    is_deeply($rWise, $sWise, 'verify equivalence');
    
    use Benchmark qw(:all);
    cmpthese(100000, {
        'regex' => sub {
            regexWise($sequence, \@dinucs);
        },
        'substr' => sub {
            substrWise($sequence, 2);
        }
    

    输出:

    1..1
    ok 1 - verify equivalence
              Rate  regex substr
    regex  11834/s     --   -85%
    substr 76923/s   550%     --
    

    对于较长的序列(10-100 kbase),优势不那么明显,但仍能胜出约 70%。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-11
      • 1970-01-01
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多