【问题标题】:sloppy matching of hash keys?散列键的草率匹配?
【发布时间】:2013-08-26 21:58:08
【问题描述】:

我目前正在比较两个基因列表,目的是找到两个列表之间的重叠基因。

目前,我将基因的名称存储为两个列表(blast1 和 blast2)的哈希键,并找到两个哈希中都存在的键(基因):

输入1:

XLOC_000157_6.21019:12.8196,_Change:1.04564,_p:0.04915,_q:0.999592      99.66   gi|475392713|dbj|AB759708.1|_Xenopus_laevis_PhyHd_mRNA_for_phytanoyl-CoA_dioxygenase_like_protein,_complete_cds
XLOC_000159_636.025:343.104,_Change:-0.890436,_p:0.00575,_q:0.999592    99.47   gi|9909981|emb|AJ278067.1|_Xenopus_laevis_mRNA_for_putative_XIRG_protein
XLOC_000561_31.1018:14.9273,_Change:-1.05905,_p:0.0073,_q:0.999592      91.57   gi|165973401|ref|NM_001113689.1|_Xenopus_(Silurana)_tropicalis_cytokine_inducible_SH2-containing_protein_(cish),_mRNA

分配第一个基因列表...

$input1 = $ARGV[0];
open my $blast1, '<', $input1 or die $!;

my $results1 = 0;
my (@blast1ID, @blast1_info, @percent_id, @split);
while (<$blast1>) {
    chomp;
    @split = split('\t');
    push @blast1_info, $split[0];
    push @percent_id, $split[1];
    push @blast1ID, $split[2];
    $results1++;
}   

print "$results1 blast hits in '$input1'\n";

push @{$blast1{$blast1ID[$_]} }, [ $blast1_info[$_], $percent_id[$_] ] for 0 .. $#blast1ID;

输入 2:

XLOC_000561_31.1018:14.9273,_Change:-1.05905,_p:0.0073,_q:0.999592      91.57   gi|165973401|ref|NM_001113689.1|_Xenopus_(Silurana)_tropicalis_cytokine_inducible_SH2-containing_protein_(cish),_mRNA
XLOC_000679_57.3461:29.2637,_Change:-0.970585,_p:0.03645,_q:0.999592    85.13   gi|51704135|gb|BC081195.1|_Xenopus_laevis_hypothetical_protein_LOC446937,_mRNA_(cDNA_clone_IMAGE:6640116),_partial_cds
XLOC_000766_10.699:6.33756,_Change:-0.755473,_p:0.0384,_q:0.999592      99.04   gi|195972824|ref|NM_001130940.1|_Xenopus_laevis_interleukin_6_signal_transducer_(gp130,_oncostatin_M_receptor)_(il6st),_mRNA

分配第二个基因列表

$input2 = $ARGV[1];
open my $blast2, '<', $input2 or die $!;

my $results2 = 0;
my (@blast2ID, @blast2_info, @percent_id);
while (<$blast2>) {
    chomp;
    @split = split('\t'); 
    push @blast2_info, $split[0];
    push @percent_id, $split[1];
    push @blast2ID, $split[2];
    $results2++;
}   
print "$results2 blast hits in '$input2'\n";

push @{$blast2{$blast2ID[$_]} }, [ $blast2_info[$_], $percent_id[$_] ] for 0 .. $#blast2ID;

查找两个哈希中都存在的键(基因):

my $intersect_count = 0;
for my $key (sort keys %blast1) {
    if (exists $blast1{$key} && $blast2{$key}) {
        $intersect_count++;
            for my $part1 (@ { $blast1{$key} } ) {
                ($hit1, $percent_id1) = @$part1;
            } 
            for my $part2 (@ { $blast2{$key} } ) {
                ($hit2, $percent_id2) = @$part2;
            }
    push @intersect, "$key\tC1:$hit1 [$percent_id1]\tC2:$hit2 [$percent_id2]\n";            
    push @intersecting_list, "$key";                
    }
}

上面的代码会找到两个列表中都存在的一个基因:

gi|165973401|ref|NM_001113689.1|_Xenopus_(Silurana)_tropicalis_cytokine_inducible_SH2-containing_protein_(cish),_mRNA

我的问题是如何调整它以便将具有相似名称的基因包含在输出中?例如我想看:

gi|186928837|ref|NM_005982.3|_Homo_sapiens_SIX_homeobox_1_(SIX1),_mRNA

找到匹配项:

gi|154142326|ref|NM_001100275.1|_Xenopus_(Silurana)_tropicalis_SIX_homeobox_1_(six1),_mRNA

有什么建议吗?

【问题讨论】:

  • NM_005982.3 怎么样 喜欢 NM_001100275.1?你想只匹配前两个字符吗?
  • 不——这很困难——我正在尝试匹配基因名称——在那个例子中是SIX_homeobox_1_(SIX1)SIX_homeobox_1_(six1)
  • 好吧,如果你想匹配基因名称的 end 大小写无关。是否有像最后 四个 字段(用下划线分隔)总是必须匹配的部分?您必须以某种方式定义“相似”。

标签: perl hash key


【解决方案1】:

您可以使用两种策略

  1. 提取您要使用的实际密钥,然后精确匹配。

    原始密钥的某些部分可能对您没有任何用处 - 删除它们。根据输入,您可能还需要进行 Unicode 规范化,并执行大小写折叠。

    在你的情况下,一个通用键

    gi|186928837|ref|NM_005982.3|_Homo_sapiens_SIX_homeobox_1_(SIX1),_mRNA
    gi|154142326|ref|NM_001100275.1|_Xenopus_(Silurana)_tropicalis_SIX_homeobox_1_(six1),_mRNA
    

    可能看起来像

    gi|ref|nm_00|_six_homeobox_1_(six1),_mrna
    
  2. 消除散列,并计算所有可能记录之间的相似性指数。要了解此类索引,您可能需要查看Levenstein edit distance。然后,您可以将特定范围内的所有其他记录视为匹配项。这是相当昂贵的,但可能会产生更好的结果。

我不知道你的问题领域,所以我不能提出任何好的建议。


您的代码存在一些问题,尤其是在查找匹配项时。看起来应该是这样的:

my $intersect_count = 0;
for my $key (sort keys %blast1) {
    if (exists $blast2{$key}) {
        $intersect_count++;
        my ($hit1, $percent_id1) = @{ $blast1{$key}[-1] };
        my ($hit2, $percent_id2) = @{ $blast2{$key}[-1] };
        push @intersect, "$key\tC1:$hit1 [$percent_id1]\tC2:$hit2 [$percent_id2]\n";
        push @intersecting_list, $key;
    }
}

区别:

  1. exists $blast1{$key} &amp;&amp; $blast2{$key} 被解析为 exists($blast1{$key}) &amp;&amp; $blast2{$key} 甚至这很愚蠢,因为我们知道 $blast1{$key} 存在:我们只是通过 keys 获取它!
  2. 当循环数组并将每一项分配给一个变量时,该变量将保留最后一项的值。即my $y; for my $x (@xs) { $y = $x } 等效于my $y = $xs[-1],但效率低于my $y = $xs[-1]

【讨论】:

  • 这是一个绝妙的答案,我担心这是一个不可能的问题。我肯定会研究莱文斯坦的编辑距离。您介意详细说明您在密钥查找中所做的编辑吗?
  • @FlyingFrog 我编辑了我的答案,并对我的修改进行了一些解释。我不建议您实际使用 Levenstein 距离。它在消除拼写错误(或点突变)等时很有用。您必须设计自己的指标,但 Levenstein 可能是其中的一部分。第一步是为自己明确定义两个键比较相等的时间。
猜你喜欢
  • 2021-11-03
  • 2021-08-15
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多