2016-10-10 58 views
1

這看起來是如此簡單的任務,但我卻很驚訝。通過合併很多文件創建一個表格

我的文本文件,每一個類型的組織命名的(如cortex.txtheart.txt

每個文件都包含兩列,列標題是gene_nameexpression_value

每個文件都包含30K左右,以40K行

我需要將這些文件合併成一個文件有29列,頭

genename, tissue1, tissue2, tissue3, etc. to tissue28 

使每一行包含一個基因,並在28個組織

下面的代碼創建包含在每個文件中的每個基因名稱的列表的陣列中的表達值:

my @list_of_genes; 

foreach my $input_file (@input_files) { 

    print $input_file, "\n"; 

    open (IN, "outfiles/$input_file"); 

    while (<IN>) { 

     if ($_ =~ m/^(\w+\|ENSMUSG\w+)\t/) { 

      # check if the gene is already in the gene list 
      my $count = grep { $_ eq $1 } @list_of_genes; 

      # if not in list, add to the list 
      if ($count == 0) { 
       push (@list_of_genes, $1); 
      } 
     } 
    } 

    close IN; 
} 

代碼的下位我希望能工作,但正則表達式只識別第一個基因名稱。

注意:我只在一個名爲「tissue1.txt」的測試文件上測試它。

的想法是創建所有文件名的數組,然後採取輪流每一個基因的名字,並通過每個文件搜索,提取每個值,並將其沿行順序寫入outfile中。

foreach my $gene (@list_of_genes) { 

    # print the gene name in the first column 
    print OUT $gene, "\t"; 

    # use the gene name to search the first element of the @input_file array and dprint to the second column 
    open (IN, "outfiles/tissue1.txt"); 

     while (<IN>) { 

     if ($_ =~ m/^$gene\t(.+)\n/i) { 
      print OUT $1; 
     } 

    } 

    print OUT "\n"; 
} 

編輯1: 謝謝鮑羅廷。你的代碼的輸出實際上是每個基因名稱的列表,每個組織中都有一個表達值。

例如Bcl20 | ENSMUSG00000000317,0.815796340254127,0.815796340245643

這比我管理的謝謝你好多了。還需要兩件事。

1)如果在一個.txt文件然後爲0的值應記錄

未發現基因名稱例如HT4 | ENSMUSG00000000031,4.75878049632381,0

2)I需要以逗號分隔的標題行,使得從每個值來保持與值(基本上是表)相關聯的組織 - 組織是文本文件

的名稱

eg從2檔heart.txt和liver.txt第一行應該是:

genename | ID,心臟,肝臟

其中genename | ID總是第一頭

+0

你必須在每一個你編寫的Perl程序的頂部總是使用strict和use warnings all''。還請設置您的編輯器以將標籤替換爲相應的空格:標籤字符是可怕的東西,不會在不同媒體上一致顯示。 – Borodin

+0

你應該使用更有意義的標識符'open(IN,「outfiles/$ input_file」)'太可怕了!我認爲通過編寫'chdir'outfiles''可以更好地服務,但使用* absolute *路徑。 – Borodin

+0

請解釋你的敘述中沒有提到的正則表達式'/ ^(\ w + \ | ENSMUSG \ w +)\ t /'。 – Borodin

回答

1

這是一個很多代碼來實現使用哈希來實現唯一性的簡單習慣用法!

它看起來像你想表達的數組,每個不同的ENSMUSG字符串中的所有文件*.txtoutfiles目錄值

如果您需要的文件是outfles目錄中的唯一文件,那麼解決方案如下所示。我已使用autodie檢查所有Perl IO操作(chdir,open,print等)的返回狀態,並僅檢查$gene值是否包含|ENSMUSG。如果您的輸入數據表現良好,您甚至不需要進行此項檢查。

請原諒我,如果這是錯誤的,因爲我目前無法訪問Perl編譯器。我通過視線檢查過,看起來很好。

use strict; 
use warnings 'all'; 
use autodie; 

chdir '/path/to/outfiles'; 

my %data; 

while (my $file = glob '*.txt') { 

    open my $fh, '<', $file; 

    while (<$fh>) { 
     my ($gene, $value) = split; 
     next unless $gene =~ /\|ENSMUSG/; 
     push @{ $data{$gene} }, $value; 
    } 
} 

print join(',', $_, @{ $data{$_} }), "\n" for keys %data; 
相關問題