2013-04-01 3 views
0

내가 ..... 내가 아래에있는 내 샘플 CSV 파일의 일부를 표시하고 을 모든 파일을 병합 할 여러 CSV 파일을을 사용하여 특정 조건에 의해 여러 CSV 파일을 병합 할은 내가 ... 펄

M1DL1_Interpro_sum.csv

IPR017690,Outer membrane, omp85 target,821 
IPR014729,Rossmann,327 
IPR013785,Aldolase,304 
IPR015421,Pyridoxal,224 
IPR003594,ATPase,179 
IPR000531,TonB receptor,150 
IPR018248,EF-hand,10 

M1DL2_Interpro_sum.csv

IPR017690,Outer membrane, omp85 target,728 
IPR013785,Aldolase,300 
IPR014729,Rossmann,261 
IPR015421,Pyridoxal,189 
IPR011991,Winged,113 
IPR000873,AMP-dependent synthetase/ligase,111 

M1DL3_Interpro_sum.csv

,536 지금 91,363,210
IPR017690,Outer membrane,905 
IPR013785,Aldolase,367 
IPR014729,Rossmann,338 
IPR015421,Pyridoxal,271 
IPR003594,ATPase,158 
IPR018248,EF-hand,3 

내가 다음 코드

@ARGV = <merge_csvfiles/*.csv>; 
print @ARGV[0],"\n"; 
open(PAGE,">outfile.csv") || die"Can't open outfile.csv\n"; 
while($i<scalar(@ARGV)) 
{ 
open(FILE,@ARGV[$i]) || die"Can't open [email protected][$i]...\n"; 
$data.=join("",<FILE>); 

close FILE; 
print"file completed...",$i+1,"\n"; 
$i++; 
} 


@data=split("\n",$data); 
@[email protected]; 

print scalar(@data); 

for($i=0;$i<scalar(@data);$i++) 
{ 
@id1=split(",",@data[$i]); 
[email protected][0]; 
@data[$j]=~s/\n//; 
if(@data[$i] ne "") 
{ 
    print PAGE "\[email protected][$i],"; 
    for($j=$i+1;$j<scalar(@data2);$j++) 
    { 
     @id2=split(",",@data2[$j]); 
     [email protected][0]; 
     if($id_1 eq $id_2) 
     { 

      @data[$j]=~s/\n//; 
      print PAGE "@data2[$j],"; 
      @data2[$j]=""; 
      @data[$j]=""; 
      print "match found at ",$i+1," and ",$j+1,"\n"; 
     } 
    } 
} 


print $i+1,"\n"; 
} 

merge_csvfiles에게 시도이 파일을 병합 할 수는 위의 코드의

출력

IPR017690,Outer membrane,821,IPR017690,Outer membrane ,728,IPR017690,Outer membrane,905 
IPR014729,Rossmann,327,IPR014729,Rossmann,261,IPR014729,Rossmann,338 
IPR013785,Aldolase,304,IPR013785,Aldolase,300,IPR013785,Aldolase,367 
IPR015421,Pyridoxal,224,IPR015421,Pyridoxal,189,IPR015421,Pyridoxal,271 
IPR003594,ATPase,179,IPR003594,ATPase,158 
IPR000531,TonB receptor,150 
IPR018248,EF-hand,10,IPR018248,EF-hand,3 
IPR011991,Winged,113 
IPR000873,AMP-dependent synthetase/ligase 

하지만 난 모든 파일이 들어있는 폴더입니다 다음 형식으로 출력하고 싶습니다 ....

IPR017690,Outer membrane,821,IPR017690,Outer membrane ,728,IPR017690,Outer membrane,905 
IPR014729,Rossmann,327,IPR014729,Rossmann,261,IPR014729,Rossmann,338 
IPR013785,Aldolase,304,IPR013785,Aldolase,300,IPR013785,Aldolase,367 
IPR015421,Pyridoxal,224,IPR015421,Pyridoxal,189,IPR015421,Pyridoxal,271 
IPR003594,ATPase,179,0,0,0,IPR003594,ATPase,158 
IPR000531,TonB receptor,150,0,0,0,0,0,0 
IPR018248,EF-hand,10,0,0,0,IPR018248,EF-hand,3 
0,0,0,IPR011991,Winged,113,0,0,0 
0,0,0,IPR000873,AMP-dependent synthetase/ligase,111,0,0,0 

아무에게도 어떻게 생각합니까? 도움을 주셔서 감사합니다

+0

"병합"의 의미를 설명 할 수 있습니까? –

+0

Miguel Prz 나는 질문을 편집했다 ... 나는 지금 내가 병합에 의해 의미했던 것이 무엇인지 알기를 바란다. – user2181315

답변

1

Miguel Prz의 설명에서 언급했듯이 병합을 수행하는 방법을 설명하지 않았지만 "원하는 출력"샘플로 판단하면 원하는 것을 나타납니다. 3 개의 모든 입력 파일의 ID가 일치하는 행을 출력 파일의 한 행에 연결하고 "0,0,0"은 주어진 파일에 나타나지 않는 행을 대신합니다. 그래서, 다음

는 :

#!/usr/bin/env perl  

use strict; 
use warnings; 

my @input_files = glob 'merge_csvfiles/*.csv'; 
my %data; 
for my $i (0 .. $#input_files) { 
    open my $infh, '<', $input_files[$i] 
    or die "Failed to open $input_files[$i]: $!"; 
    while (<$infh>) { 
    chomp; 
    my $id = (split ',', $_, 2)[0]; 
    $data{$id}[$i] = $_; 
    } 
    print "Input file read: $input_files[$i]\n"; 
} 

open my $outfh, '>', 'outfile.csv' or die "Failed to open outfile.csv: $!"; 
for my $id (sort keys %data) { 
    my @merge_data; 
    for my $i (0 .. $#input_files) { 
    push @merge_data, $data{$id}[$i] || '0,0,0'; 
    } 
    print $outfh join(',', @merge_data) . "\n"; 
} 

첫 번째 루프는 배열의 해시에 각 파일의 모든 라인을 수집합니다. 해시 키는 ID이므로 모든 파일의 해당 ID에 대한 행은 함께 보존되며 각 키의 값은 각 파일의 해당 ID와 연관된 행의 배열입니다 (참조). 배열을 사용하면 누락 된 값과 존재하지 않는 값을 추적 할 수 있습니다.

그런 다음 두 번째 루프는 해당 해시 키 (알파벳 순서)를 가져 와서 각각에 대해 해당 ID와 연결된 값의 임시 배열을 만들고 누락 값에 "0,0,0"을 대입합니다 단일 문자열로 변환 한 다음 출력 파일에 출력합니다.outfile.csv에서

결과는 다음과 같습니다

IPR000531,TonB receptor,150,0,0,0,0,0,0 
0,0,0,IPR000873,AMP-dependent synthetase/ligase,111,0,0,0 
IPR003594,ATPase,179,0,0,0,IPR003594,ATPase,158 
0,0,0,IPR011991,Winged,113,0,0,0 
IPR013785,Aldolase,304,IPR013785,Aldolase,300,IPR013785,Aldolase,367 
IPR014729,Rossmann,327,IPR014729,Rossmann,261,IPR014729,Rossmann,338 
IPR015421,Pyridoxal,224,IPR015421,Pyridoxal,189,IPR015421,Pyridoxal,271 
IPR017690,Outer membrane, omp85 target,821,IPR017690,Outer membrane, omp85 target,728,IPR017690,Outer membrane,905 
IPR018248,EF-hand,10,0,0,0,IPR018248,EF-hand,3 

편집 : 의견 OP에 의해 요구 된 추가 설명

는 u는 나에게 내 $ 아이디 = (분할 '의 작업을 expalain 수 있습니다 , ', $ _, 2) [0]; 이 프로그램

my $id = (split ',', $_, 2)[0]; 및 $ #은 읽은 텍스트의 마지막 줄의 첫 번째 쉼표하기 전에 텍스트를 가져옵니다

  • 내가의 데이터를 넣어 어떤 변수 지정하지 않았기 때문에 while (<$infh>)은 기본 변수 $_으로 읽습니다.
  • split ',', $_, 2$_ 값을 쉼표로 구분 된 필드 목록으로 나눕니다. 끝에있는 2은 최대 2 개의 필드 만 생성하도록 지시합니다. 코드는 2 없이는 정상적으로 작동하지만 첫 번째 필드 만 필요하므로 더 많은 부분으로 분할 할 필요가 없습니다.
  • split 명령에 대해 (...)[0]을 입력하면 반환 된 필드 목록이 (익명) 배열로 바뀌고 해당 배열의 첫 번째 요소가 반환됩니다. 내가 my @fields = split ',', $_, 2; my $id = $fields[0];이라고 쓰여진 것과 같지만 더 짧고 여분의 변수는 없습니다.

$#array 정도로 for my $i (0 .. $#array) 단지 "@array의 모든 요소를 ​​통해 루프 인덱스"를 의미 어레이 @array 가장 높은 번호의 인덱스를 반환한다. (인덱스 카운터의 값을 필요로하지 않는다면, 대신 for my $filename (@input_files)을 사용하여 배열의 데이터를 직접 루프했을 것입니다.하지만 만약 누락 된 값을 추적하는 것이 덜 편리했을 것입니다. 그런 식으로 끝냈습니다.)

+0

정말 고마워.하지만 내 expalain me $ id = (split ',', $ _, 2) [0]; 그리고이 프로그램에서 $ # perl에 익숙하지 않다. 고맙다. – user2181315

+0

@ user2181315 : 나는 당신이 물어 본 것에 대한 설명을 추가하기 위해 나의 대답을 편집했다. –