2016-12-04 63 views
0

我想創建一個從文件1有值輸出文件和文件1文件2打印與哈希值從不同的文件

行:

CHR1袖釦外顯子708356 708487 1000 - 。
gene_id「CUFF.3」; transcript_id「CUFF.3.1」;外顯子編號「5」; FPKM 「3.1300591420」;壓裂「1.000000」; conf_lo「2.502470」; conf_hi 「3.757648」; cov「7.589085」; chr1Cufflinks外顯子708356 708487。 - 。 gene_id「XLOC_001284」; transcript_id 「TCONS_00007667」;外顯子編號「7」; gene_name「LOC100288069」; oId 「CUFF.15.2」; nearest_ref「NR_033908」; class_code「j」; tss_id 「TSS2981」;

從文件2中的線:

CUFF.48557
CHR4:160253850-160259462:160259621-160260265:160260507-160262715

從該文件中的第二列是唯一id(uniq_id)。

我想在下面的格式輸出文件: transcript_id(CUFF_id)uniq_id gene_id(XLOC_ID)FPKM

我的腳本需要XLOC_ID和FPKM值從第一個文件,並從第二有兩列一起打印出來文件。

#!/usr/bin/perl -w 

use strict; 

my $v_merge_gtf = shift @ARGV or die $!; 
my $unique_gtf = shift @ARGV or die $!; 

my %fpkm_hash; 
my %xloc_hash; 

open (FILE, "$v_merge_gtf") or die $!; 
while (<FILE>) { 
    my $line = $_; 
    chomp $line; 
    if ($line =~ /[a-z]/) { 
     my @array = split("\t", $line); 
     if ($array[2] eq 'exon') { 
      my $id = $array[8]; 
      if ($id =~ /transcript_id \"(CUFF\S+)/) { 
       $id = $1; 
       $id =~ s/\"//g; 
       $id =~ s/;//; 
      } 

      my $fpkm = $array[8]; 
      if ($fpkm =~ /FPKM \"(\S+)/) { 
       $fpkm = $1; 
       $fpkm =~ s/\"//g; 
       $fpkm =~ s/;//; 
      } 

      my $xloc = $array[17]; 
      if ($xloc =~ /gene_id \"(XLOC\S+)/) { 
       $xloc = $1; 
       $xloc =~ s/\"//g; 
       $xloc =~ s/;//; 
      } 
      $fpkm_hash{$id} = $fpkm; 
      $xloc_hash{$id} = $xloc; 
     } 
    } 
} 

close FILE; 


open (FILE, "$unique_gtf") or die $!; 
while (<FILE>) { 
    my $line = $_; 
    chomp $line; 
    if ($line =~ /[a-z]/) { 
     my @array = split("\t", $line); 
     my $id = $array[0]; 
     my $uniq = $array[1]; 
     print $id . "\t" . $uniq . "\t" . $xloc_hash{$id} . "\t" . $fpkm_hash{$id} . "\n"; 
    } 
} 

close FILE; 

我初始化哈希的文件之外,但我得到了下面的錯誤每個袖口值:

CUFF.24093
chr17:3533641-3539345:3527526-3533498:3526786-3527341 :(。)3524707-3526632

未初始化值的在串聯或串在ex_1.pl 線55,線9343.

使用使用級聯(。)中的未初始化值或ex_1.pl處的字符串 第55行,9343行。

如何解決此問題?

謝謝!

+0

66是哪裏? – simbabque

+0

我對此感到抱歉。 錯誤是指打印聲明行: print $ id。 「\ t」。 $ uniq。 「\ t」。 $ xloc_hash {$ id}。 「\ t」。 $ fpkm_hash {$ id}。 「\ n」 個; –

+0

那麼,其中一個值是未初始化的。哪一個?也許你的輸入數據不一致。 – simbabque

回答

0

我認爲警告信息是因爲$id密鑰(CUFF.24093),第行上的第二個文件沒有包含在第一個文件中創建的哈希中。

第二個文件中的ID是否可能不包含在第一個文件中?這似乎就是這種情況。

如果是這樣,你只是想跳過這個未知的ID,您可以一行添加到您的程序,如:

my $id = $array[0]; 
my $uniq = $array[1]; 

next unless exists $fpkm_hash{$id}; # add this line 

print $id . "\t" . $uniq . "\t" . $xloc_hash{$id} . "\t" . $fpkm_hash{$id} . "\n"; 

這將繞過以下print聲明,回去的頂部while循環並在下一行中讀取並繼續處理。

這取決於你想,如果你遇到一個未知的ID採取什麼行動。

更新:我想我可能會對您的代碼進行一些觀察/改進。

my $v_merge_gtf = shift @ARGV or die $!; 
my $unique_gtf = shift @ARGV or die $!; 

錯誤變量$!這裏沒有任何意義(這是事實,我最近才使用Perl發現即使14年後)。 $!僅用於系統調用(涉及操作系統的地方)。最常見的是open,關閉文件,opendir和closedir用於目錄。如果在打開/關閉文件或目錄時發生錯誤,$!將包含錯誤消息。 (在我包含的代碼看我怎麼處理這個 - 我創建了一個消息,$usage如果shift沒有成功打印

而不是使用2個哈希值來存儲信息的,我用1個散列,%data的。好處是它會使用更少的內存,(因爲它只存儲1組密鑰而不是2),儘管如果你願意,你可以使用2組。這些文件。您使用的2論據的做法已經過時,而且安全性較差(對於原因,我不會進入這裏的細節)。此外,詞法文件句柄我用過,my $mrgmy $unique是較新的方式來創建文件句柄(而不是使用FILE爲您的2打開)。

您可以直接分配給$line在while循環一樣while (my $line = <FILE>),而不是你做的方式。在我的示例程序中,我沒有分配到$line,而是依靠默認變量$_。 (它簡化了以下兩條陳述,next unless /\S/; my @array = split /\t/;)。對於第一個文件,我沒有chomp,因爲您只是在字符串內解析並且沒有使用字符串末尾的任何內容。 chomp是必要的第二while循環,因爲如果沒有由chomp除去它的第二可變my $uniq = ...將具有在其端部換行。

我不知道你這種說法,if ($line =~ /[a-z]/)是什麼意思。我假設你想檢查空行並只處理含有非空間數據的行。這就是我爲什麼寫next unless /\S/;的原因。 (表示跳過以下語句並進入while循環的頂部並閱讀下一條記錄)。

你的第一while循環工作,因爲你在輸入文件中沒有任何錯誤。如果出現錯誤,您編寫代碼的方式可能會成爲問題。

如果以下if語句錯誤,語句my $id = $array[8];給出了$id的一個值,該值將被錯誤地使用。 (對於其他兩個要捕獲的變量,$fpkm$xloc也是如此)。你可以在我的代碼示例中看到我是如何處理這個的。

在我的代碼中,如果匹配沒有成功,我就死了,你可能不想要die,而是說match or next來嘗試下一行數據。這取決於你想如何處理失敗的比賽。

而且在這一行$array[8] =~ /gene_id "(CUFF\S+)";/,請注意,我把";以下捕獲的數據,所以沒有必要從捕獲的數據刪除(如你在換人做)

好了,我知道這對你的代碼是一個長期的評論,但是我希望你對我爲什麼推薦給出的改變有一些好的想法。

or die "Could not find ID in $v_merge_gtf (line# $.)";

$.是正被讀取的文件的行號。

#!/usr/bin/perl 
use warnings; 
use strict; 

my $usage = "USAGE: perl $0 merge_gtf_file unique_gtf_file\n"; 

my $v_merge_gtf = shift @ARGV or die $usage; 
my $unique_gtf = shift @ARGV or die $usage; 

my %data; 

open my $mrg, '<', $v_merge_gtf or die $!; 

while (<$mrg>) { 
    next unless /\S/; 
    my @array = split /\t/; 
    if ($array[2] eq 'exon') { 

     $array[8] =~ /gene_id "(CUFF\S+)";/ 
      or die "Could not find ID in $v_merge_gtf (line# $.)"; 
     my $id = $1; 

     $array[8] =~ /FPKM "(\S+)";/ 
      or die "Could not find FPKM in $v_merge_gtf (line# $.)"; 
     my $fpkm = $1; 

     $array[17] =~ /gene_id "(XLOC\S+)";/ 
      or die "Could not find XLOC in $v_merge_gtf (line# $.)"; 
     my $xloc = $1; 

     $data{$id}{fpkm} = $fpkm; 
     $data{$id}{xloc} = $xloc; 
    } 
} 
close $mrg or die $!; 


open my $unique, '<', $unique_gtf or die $!; 
while (<$unique>) { 
    next unless /\S/; 
    chomp; 
    my ($id, $uniq) = split /\t/; 
    print join("\t", $id, $uniq, $data{$id}{fpkm}, $data{$id}{xloc}), "\n"; 
} 

close $unique or die $!; 
+0

非常感謝您提出寶貴的建議。 我使用$ id修改了行,而不是transcript_id我使用了gene_id。 從這點開始,哈希中的$ id和數組中的$ id開始保持一致,並修復了錯誤。 –

+0

@Olha Kholod我添加了很多信息的更新我的帖子 –

+0

謝謝你逐行解釋代碼。我非常感謝你的時間和工作,並同意你的大部分陳述。我是編程新手,所以我的一些行可能不如您在更新中所建議的那樣複雜。我將努力提高我的技能,以便在未來克服這些問題。 –