-4

次のようなデータファイル(タブ区切り)があります。

chr1    38045559    38046059    chr1:38045559-38046559_NM_001142726_C1orf122_+,chr1:38045559-38046559_NM_198446_C1orf122_+,chr1:38045952-38046952_NM_024640_YRDC_-
chr1    205291045   205291545   chr1:205290545-205291545_NM_018566_YOD1_-
chr1    1499717 1500625 chr1:1499625-1500625_NM_014188_SSU72_-
chr1    1679941 1680441 chr1:1679441-1680441_NM_001198995_NADK_-
chr1    1699769 1700657 chr1:1699269-1700269_NM_023018_NADK_-,chr1:1699657-1700657_NM_001198993_NADK_-
chr1    1701368 1701868 chr1:1700868-1701868_NM_001198994_NADK_-
chr1    1812386 1812886 chr1:1811886-1812886_NM_002074_GNB1_-
chr1    2066155 2066655 
chr1    2149493 2149993 chr1:2149493-2150493_NM_003036_SKI_+
chr1    2312573 2313353 chr1:2312353-2313353_NM_024848_MORN1_-,chr1:2312573-2313573_NM_007033_RER1_+

どこ:

  • 最初の3列は座標と
  • 最後の列には、0個以上の注釈レコードのセットが含まれています
    • 各注釈レコードはコンマで区切られます
    • 注釈レコード内のフィールドは、アンダースコアまたはコロンで区切られます

私が欲しいのは、最初の3つの列をそのまま取得し、各注釈レコードから5番目のフィールドを取得することです。たとえば、行1の場合、出力は次のようになります。

chr1    38045559    38046059   C1orf122
                               C1orf122
                               YRDC

私が行ったことは、コンマ「、」に基づいて最後の列のデータをすでに分割していることです。

を使用してtr ',' '\t' <input>temp1

今私が持っているのはこのようなファイルです

chr1    38045559    38046059    chr1:38045559-38046559_NM_001142726_C1orf122_+  chr1:38045559-38046559_NM_198446_C1orf122_+ chr1:38045952-38046952_NM_024640_YRDC_-
chr1    205291045   205291545   chr1:205290545-205291545_NM_018566_YOD1_-
chr1    1499717 1500625 chr1:1499625-1500625_NM_014188_SSU72_-
chr1    1679941 1680441 chr1:1679441-1680441_NM_001198995_NADK_-
chr1    1699769 1700657 chr1:1699269-1700269_NM_023018_NADK_-   chr1:1699657-1700657_NM_001198993_NADK_-
chr1    1701368 1701868 chr1:1700868-1701868_NM_001198994_NADK_-
chr1    1812386 1812886 chr1:1811886-1812886_NM_002074_GNB1_-
chr1    2066155 2066655 
chr1    2149493 2149993 chr1:2149493-2150493_NM_003036_SKI_+
chr1    2312573 2313353 chr1:2312353-2313353_NM_024848_MORN1_-  chr1:2312573-2313573_NM_007033_RER1_+

さて、希望の出力形式に到達するには、少し専門知識が必要です。

python / perl/shellで目的の出力を取得するようにガイドしてください。

4

3 に答える 3

1

スクリプトファイルは微調整と再利用の最有力候補であり、少なくとも適度に複雑であるため、このためにスクリプトファイルを使用することを検討します。さらに、コードに適したモジュールをより簡単に使用できます。Text::CSVcsvファイルを安全に読み取り、Text::ParseWordsネストされたフィールドを処理します。

以下のスクリプトはデモンストレーション用です。ファイルハンドル*DATAをに変更*ARGVして、スクリプトが引数ファイルを解析するようにすることができます。例:

perl script.pl file.csv > output.txt

コード:

use strict;
use warnings;
use Text::CSV;
use Text::ParseWords;

my $csv = Text::CSV->new({                     # create csv object
        sep_char => "\t",                      # delimiter is tab
    });  

while(my $row = $csv->getline(*DATA)) {        # read from file handle
    my @anno = quotewords(',', 0, $row->[-1]); # get list of fields
    @anno = "" unless @anno;                   # avoid empty list
    for (@anno) {                              # for each field
        my @inner = quotewords('[:_]', 0, $_);    # get inner fields
        my $anno = $inner[-2] // "";              # take second last
        print join "\t", @$row[0 .. 2], $anno;
        print $/;
        $_ = "" for @$row;                     # clear primary row once printed
    }
}
__DATA__
chr1    38045559    38046059    chr1:38045559-38046559_NM_001142726_C1orf122_+,chr1:38045559-38046559_NM_198446_C1orf122_+,chr1:38045952-38046952_NM_024640_YRDC_-
chr1    205291045   205291545   chr1:205290545-205291545_NM_018566_YOD1_-
chr1    1499717 1500625 chr1:1499625-1500625_NM_014188_SSU72_-
chr1    1679941 1680441 chr1:1679441-1680441_NM_001198995_NADK_-
chr1    1699769 1700657 chr1:1699269-1700269_NM_023018_NADK_-,chr1:1699657-1700657_NM_001198993_NADK_-
chr1    1701368 1701868 chr1:1700868-1701868_NM_001198994_NADK_-
chr1    1812386 1812886 chr1:1811886-1812886_NM_002074_GNB1_-
chr1    2066155 2066655 
chr1    2149493 2149993 chr1:2149493-2150493_NM_003036_SKI_+
chr1    2312573 2313353 chr1:2312353-2313353_NM_024848_MORN1_-,chr1:2312573-2313573_NM_007033_RER1_+
于 2012-10-08T10:32:15.237 に答える
1

コマンドラインのパラメーターとして入力ファイルを期待するこのソリューションを提案します

use strict;
use warnings;

while (<>) {
  chomp;
  my @columns = split "\t";

  print join "\t", @columns[0, 1, 2];

  unless ($columns[3]) {
    print "\n";
    next;
  }

  my @records = split /,/, $columns[3];
  my $tabs = 1;
  for (@records) {
    my @notes = split /[_:]/;
    print "\t" x $tabs;
    print $notes[4], "\n";
    $tabs = 4;
  }
}

出力

chr1    38045559    38046059    C1orf122
                C1orf122
                YRDC
chr1    205291045   205291545   YOD1
chr1    1499717 1500625 SSU72
chr1    1679941 1680441 NADK
chr1    1699769 1700657 NADK
                NADK
chr1    1701368 1701868 NADK
chr1    1812386 1812886 GNB1
chr1    2066155 2066655
chr1    2149493 2149993 SKI
chr1    2312573 2313353 MORN1
                RER1

不整合は、さまざまな長さのフィールドのタブ分離が原因であることに注意してください

アップデート

このバージョンでは、出力が配列に蓄積され、各列の最大幅が評価されるため、適切な固定フィールド幅で表示できます。

use strict;
use warnings;

my @output;

while (<>) {
  chomp;
  my @columns = split "\t";
  my @outrec = @columns[0,1,2];

  if ($columns[3]) {

    my @records = split /,/, $columns[3];
    for (@records) {
      my @notes = split /[_:]/;
      $outrec[3] = $notes[4];
      push @output, [ @outrec ];
      @outrec = ();
    }
  }
  else {
      push @output, \@outrec;
  }
}

my @sizes;
for (@output) {
  for my $i (0..3) {
    my $length = length($_->[$i] // '');
    $sizes[$i] = $length unless $sizes[$i] and $sizes[$i] > $length;
  }
}

for my $outrec (@output) {
  printf "%-*s %-*s %-*s %-*s\n", map { $sizes[$_], $outrec->[$_] // ''} 0..3;
}

出力

chr1 38045559  38046059  C1orf122
                         C1orf122
                         YRDC    
chr1 205291045 205291545 YOD1    
chr1 1499717   1500625   SSU72   
chr1 1679941   1680441   NADK    
chr1 1699769   1700657   NADK    
                         NADK    
chr1 1701368   1701868   NADK    
chr1 1812386   1812886   GNB1    
chr1 2066155   2066655           
chr1 2149493   2149993   SKI     
chr1 2312573   2313353   MORN1   
                         RER1    
于 2012-10-08T11:07:55.330 に答える
0

このPerlソリューションはあなたが望むことをしますか?あなたはそれを調整する必要があるかもしれません:

perl -ane '
    @names = split /,/, $F[-1];
    print +(join "\t", @F[0 .. 2], join "\n\t\t\t", map +(split /_/)[3], @names), "\n";
'

アップデート:

-n入力を1行ずつ処理するようにPerlに指示します。

-a各行を配列@Fに分割するようにPerlに指示します。

最後のフィールドは,、新しい配列@namesに分割されます。次に、最初の3つのフィールドが印刷され、その後に改行と3つのタブで結合された名前が続きます。各名前は、アンダースコアで分割して4番目のメンバーを返すことにより、@namesから取得されます。

Text :: Tableを使用して出力をフォーマットします:

perl -MText::Table -ane '
    BEGIN { $t = Text::Table->new }
    @names = split /,/, $F[-1];
    @n = map +(split /_/)[3], @names;
    my $f;
    $t->add($f++ ? (("") x 3)
                 : @F[0 .. 2], $_)
        for  @n ? @n : ("")
    }{
       print $t'
于 2012-10-08T10:09:08.420 に答える