2014-03-05 47 views
0

我有10個文件夾,並在每個文件夾中,我有兩個文件(CSV,逗號delimeted)在以下格式。解析CSV文件和匹配

文件1:

Ensembl Gene ID,Ensembl Transcript ID,Exon Chr Start (bp),Exon Chr End (bp),Exon Rank in Transcript, Transcript count,Gene End (bp) ,Gene Start (bp),Strand 
ENSG00000271782,ENST00000607815,50902700,50902978,1,1,50902978,50902700,-1 
ENSG00000232753,ENST00000424955,103817769,103817825,1,1,103828355,103817769,1 
ENSG00000232753,ENST00000424955,103827995,103828355,2,1,103828355,103817769,1 
ENSG00000225767,ENST00000424664,50927141 50927168,1,1,50936822,50927141,1 

文件2:

number,Start pos,End Pos 
1,41035,41048 
3,36738,36751 
3,38169,38182 
3,40264,40277 

我試圖匹配第二文件firstfile

  1. 在第二個文件的colum1數量是關鍵在第一個文件中記錄編號。
  2. 從第一個文件

在需要時輸出提取最後3個colums:

1,ENSG00000271782,41035,41048,50902978,50902700,-1 
3,ENSG00000225767,36738,36751,50936822,50927141,1 
3,ENSG00000225767,38169,38182,50936822,50927141,1 
3,ENSG00000225767,40264,40277,50936822,50927141,1 

我已經開始從第二使用TexT::CSV讀書,但需要幫助。

use strict; 
use warnings; 
use lib 'C:/Perl/lib'; 
use Text::CSV; 

my $file1 = "infile1"; 
open my $fh, "<", $file1 or die "$file1: $!"; 
my $file2 = "infile2" 
open my $fh2, "<", $file2 or die "$file2: $!"; 

my $csv = Text::CSV->new ({ 
    binary => 1, 
    auto_diag => 1, 
    }); 


while (my $row = $csv->getline ($fh2)) { 
    print "@$row\n"; # I am stuck in extraction ? do I need to put another while loop for fh1 
    } 

close $fh1; 
close $fh2; 
+0

第一個文件中沒有「關鍵記錄號」。沒有這樣的列,並且該ID上沒有'3'。 – TLP

+0

我的意思是關鍵記錄號是數字表示第一個文件的Ensembl Gene ID列中的記錄號。 1 ENSG00000271782 – user61398

+0

'3'仍然不是'ENSG00000225767'。這些文件之間沒有關係。 – TLP

回答

0

由於在雙引號內沒有逗號,因此您可以在逗號上使用split而不是使用Text::CSV(這是一個很好的模塊)。鑑於此,下面會產生你想要的輸出:

use strict; 
use warnings; 
use autodie; 

my ($num, %hash) = 0; 
my ($file1, $file2) = qw/inFile1 inFile2/; 

open my $fh1, '<', $file1; 
while (<$fh1>) { 
    next if $. == 1; 
    chomp; 
    my @fields = split /,/; 

    $num++ if !$hash{ $fields[0] }++; 
    push @{ $hash{$num} }, [ @fields[ 0, 6 .. 8 ] ]; 
} 
close $fh1; 

open my $fh2, '<', $file2; 
while (<$fh2>) { 
    next if $. == 1; 
    chomp; 
    my @fields = split /,/; 

    if (my @arr = @{ $hash{ $fields[0] }->[0] }) { 
     splice @arr, 1, 0, @fields[ 1, 2 ]; 
     print join(',', $fields[0], @arr), "\n"; 
    } 
} 
close $fh2; 

這使用哈希:1)跟蹤看出基因的ID,和2)構建陣列(HoAoA)的陣列的哈希值。計數 - 您的「關鍵記錄」 - 在唯一基因ID上遞增,所以#1跟蹤這些ID以確保$num僅在基因ID尚未出現時才增加。使用數字2(HoAoA)是因爲存在多個相同基因ID的實例,但只有第一個實例的值用於打印。 (但我注意到,第二個跳過#2,它是多實例基因ID)。也許你只需要一個數組散列(HoA),但它的運行方式很好 - 或者你可以根據需要修改它。也就是說,如果您不打算使用多個基因ID信息,則可以簡化代碼。

輸出你的數據集:

1,ENSG00000271782,41035,41048,50902978,50902700,-1 
3,ENSG00000225767,36738,36751,50936822,50927141,1 
3,ENSG00000225767,38169,38182,50936822,50927141,1 
3,ENSG00000225767,40264,40277,50936822,50927141,1 

希望這有助於!

+0

感謝Kenosis您的回覆。它幫助了我很多你的代碼。我能夠跑並遵循第一部分,直到收到$ fh1。該程序正在第二部分停止,具體在這一行:if(my @arr = @ {$ hash {$ fields [0]} - > [0]})出現錯誤「無法使用未定義的值作爲ARRAY參考「。任何說法。 – user61398

+0

@ user61398 - 非常歡迎。這個錯誤提示'@ fields'不會被'while(<$fh2>){...'循環中的'split'初始化,因此是「未定義的值」。爲了調試這個,你可以在'split'後面加'print $。,「\ n」;來查看發生錯誤的文件的行號。如果它在文件開始時是正確的,那麼你可能需要調整你正在分割的東西。但是,如果它進一步進入文件,它可能是一個'不好'的數據線。 – Kenosis

0

這個問題的有趣的部分是,你需要閱讀的文件1的邏輯,直到它的前進檔2和讀取文件2邏輯的,直到它的前進檔1和邏輯來知道如何行動時,一個是在另一個之後,以及何時平衡。

您需要跟蹤唯一的基因集合ids和它們在列表中的序數位置。所以,當你閱讀file2的第二行時,你會知道如何跳過file1的第二行和第三行,但是當你讀完文件1中的第三行和第四行時,也知道不要跳過file1以及更多。

或者你可以讀取file1到內存中,並創建一個數組的行數組,以便例如

file1arr[1] = [ $line1 ] 
    file1arr[2] = [ $line2, $line3 ] 
    file1arr[3] = [ $line4 ] 

所以當你遍歷文件2,文件1,從所有的線是在對應於文件2的數列數組的索引以整齊的小數組引用。

然後它只是一個迭代file1行數組的練習,將它們拆分並構建輸出行。