Perl:如果值的数组相交,则从2个哈希值中打印键

时间:2015-08-17 12:50:58

标签: arrays perl hash bioinformatics

我有2个文件,如下所示:

File1 :除了最后一列之外的所有列都是以制表符分隔的

space   start   end width   names   score.data  
1   1   1873    24409   22537   DDX11L1 NA
2   1   4361    39370   35010   WASH7P  NA
23  1   690244  724068  33825   LOC100288069    NA
24  1   742750  765214  22465   FAM87B  "rs1;rs2;rs3,"
25  1   751585  772902  21318   LINC00115   "rs3;rs4"
26  1   752970  804826  51857   LINC01128   "rs5;rs6;rs7;rs8;rs9"
27  1   793450  822182  28733   FAM41C  "rs9;rs10;rs11"
28  1   842197  865072  22876   LOC100130417    "rs12;rs13;rs14;rs15;rs16"
29  1   851120  889961  38842   SAMD11  "rs14;rs15;rs16;rs17"
30  1   869582  904679  35098   NOC2L   "rs13;rs17;rs20;rs25;rs27"  
31  1   885966  911099  25134   KLHL17  "rs23;rs25;rs34;rs49"
78  1   1582938 1634243 51306   SLC35E2B    rs45

File2 :除了最后一列之外的所有列都是以制表符分隔的

space   start   end width   names   score.data  
1   1   1096679 1097517 839     DMR1 rs2;rs3  
2   1   1229025 1229590 566     DMR2 rs4  
3   1   1267955 1269432 1478    DMR3 rs7;rs8;rs9  
4   1   1279248 1279795 548     DMR4 rs9;rs10  
5   1   1372628 1374653 2026    DMR5 rs11;rs12;rs14;rs18  
6   1   1842116 1842456 341     DMR6 NA  
7   1   1896556 1897211 656     DMR7 rs13;rs17;rs20  

所需的输出:所有列标签分隔

DMR1 FAM87B LINC00115   
DMR2 LINC00115    
DMR3 LINC01128 FAM41C    
DMR4 LINC01128 FAM41C
DMR5 FAM41C LOC100130417 SAMD11
DMR7 SAMD11 NOC2L 

基本上,我需要检查来自score.data的{​​{1}}条目(rs2,rs3 ......)是否与file2的{​​{1}}条目相交。如果他们这样做,我应该从score.data获取密钥(file1),并从names column获取相应的密钥(file2)。

例如names column中的file1有得分。数据DMR1file2的得分数据rs2;rs3以及rs1;rs2;rs3的{​​{1}}相交在FAM87B

中{1}}

到目前为止,我写的大部分代码都是为了清理第一个文件""和NA条目和创建哈希:

rs3;rs4

我尝试在stackoverflow上搜索其他哈希比较问题,并且所有哈希在两个哈希中都有相同的键。我还发现Array::Utils工具与两个数组相交,但我真的不确定如何在我的问题中实现它。

感谢您抽出宝贵时间回答我的问题,我将非常感谢您的想法和解决方案。

1 个答案:

答案 0 :(得分:2)

这会按照你的要求行事。它构建一个哈希%mapping,将每个分数条目与它们在File1中对应的所有名称相关联,然后在通过File2读取时查询该哈希,以构建由分数条目连接的名称列表

程序期望两个输入文件的路径作为comamnd行的参数,如

请注意,我刚刚在空格上拆分每条记录,因为示例数据中的分隔符不一致

DRM7的输出包含您所需输出中缺少的LOC100130417。这是正确的,因为来自File2的DRM7的分数条目rs13也出现在File1的LOC100130417行中

perl find_joined.pl path/to/file1 path/to/file2
use strict;
use warnings;
use v5.10.1;
use autodie;

my %mapping;

{
    open my $fh, '<', $ARGV[0];
    <$fh>; # Drop the header line

    while ( <$fh> ) {
        my @fields = split;
        my $name = $fields[-2];
        my @entries = $fields[-1] =~ /[^";]+/g;
        push @{ $mapping{$_} }, $name for @entries;
    }

    delete $mapping{NA};
}

open my $fh, '<', $ARGV[1];
<$fh>; # Drop the header line

while ( <$fh> ) {
    my @fields = split;
    my $name = $fields[-2];
    my @entries = $fields[-1] =~ /[^";]+/g;

    my %matching;
    @matching{@$_} = () for grep defined, @mapping{@entries};

    if ( keys %matching ) {
        print join(' ', $name, sort keys %matching), "\n"
    }
}

输出

DMR1 FAM87B LINC00115
DMR2 LINC00115
DMR3 FAM41C LINC01128
DMR4 FAM41C LINC01128
DMR5 FAM41C LOC100130417 SAMD11
DMR7 LOC100130417 NOC2L SAMD11