2014-09-05 51 views
0

我的数据集(csv文件)包含大量正在进行多项测试的个人。如果任何测试完成,测试日期将在那里。在第二栏中有个人所属组织的代码。我们有大约40个独特的代码/组织。我试图在这个大数据集中检查每个组织(即唯一代码)的所有唯一代码,以获取包含所有组织特定数据的文件。注意我还需要以月 - 年的形式获取日期,而不是日 - 月 - 年。 这里是我的数据集怎么看起来像一个感觉:在perl中应用2个grep条件

Patient,Code,test1,test2,test3 
P1,072,,25-Mar-14,           
P2,072,29-May-14,,           
P3,073,,03-Jan-14,         
P4,074,,,16-Feb-14           
P5,075,,09-Jul-14,           
P6,075,08-Jun-14,, 

输出应该是类似的东西: 包含标题,看起来像072文件:

Patient,Code,test1,test2,test3 
P1,072,,25-Mar-14,           
P2,072,29-May-14,, 

与073标题另一个文件看起来类似于:

Patient,Code,test1,test2,test3 
P3,073,,03-Jan-14, 

这里是我写的代码。它会保存唯一的代码并创建一个具有组织特定代码的csv文件,但不会为每个文件填充相应的信息(仅与特定组织有关的数据,并用mm-yy替代dd-mm-yy。任何人都可以告诉我什么是错误的代码?

use feature ':5.12'; 
use strict; 
use warnings; 
use autodie; 

my $dataset   = 'R:/dataset/'; 
my $output_directory = 'R:/results/'; 

open my $infh, '<', "$dataset/CH_dataset.csv"; 

my %codes =(); 
while (<$infh>) { 
    chomp; 
    my @columns = split ","; 
    print "$columns[1]\n" if !$codes{ $columns[1] }++; 
    my @unique_codes = keys %scodes; 

    foreach my $unique_codes (@unique_codes) { 
     open my $outfh, ">>", "$output_directory/CH_$unique_codes\_v$version.$update.csv"; 
     print $outfh $_ 
      if (/"$unique_codes"/ 
      and s/\d\d\-Jan\-/Jan\-/g | s/\d\d\-Feb\-/Feb\-/g | s/\d\d\-Mar\-/Mar\-/g | s/\d\d\-Apr\-/Apr\-/g 
      | s/\d\d\-May\-/May\-/g | s/\d\d\-Jun\-/Jun\-/g | s/\d\d\-Jul\-/Jul\-/g | s/\d\d\-Aug\-/Aug\-/g 
      | s/\d\d\-Sep\-/Sep\-/g | s/\d\d\-Oct\-/Oct\-/g | s/\d\d\-Nov\-/Nov\-/g | s/\d\d\-Dec\-/Dec\-/g); 
    } 
} 

感谢您的帮助!

+0

例如一个csv文件,标题中的代码为072,以下内部病人代码test1 test2 test3 P1 072 25-Mar-14 P2 072 29-May-14 – fmfshog 2014-09-05 11:22:11

+0

你为什么在','上进行分割?您的列似乎被空间隔开。 – Toto 2014-09-05 11:22:31

+0

@ M42我的数据集实际上是一种csv格式。我已经编辑过它的样子 – fmfshog 2014-09-05 11:27:28

回答

1

我也有过类似的任务一次。我使用一个散列来容纳所有必需的文件句柄,并关闭 他们都只是退出该代码之前如果您的数据符合严格的格式,则下面的内容应该可以工作。

use 5.14.0; 
use Carp; 

my $infile = $ARGV[0]; 

my %fh; # this hash will have your codes as keys and the 
      # corresponding filehandles as values. 

# {{{ Open the infile and work 
open(INFILE, "<$infile") or croak("Could not open $infile"); 
my $lineCnt = 0; 
my $header = readline(INFILE); # skip the first line. 
chomp($header); 
my $justOpened = 0; 
while (my $line = readline(INFILE)) { 
    chomp($line); 
    if ($line =~ m/^\s*\#/ or $line =~ m/^\s*$/) { next; } 
    my @ll = split(/,/, $line); 
    my $code = $ll[1]; 
    my $dmy; 
    for my $temp (@ll) { 
     if ($temp =~ m/\d{2}-\w{3}-\d{2}/) { 
      $dmy = $temp; 
     } 
    } 
    my @dmy = split(/-/, $dmy); 
    my $nmy = $dmy[1] . '-' . $dmy[2]; 
    $line =~ s/$dmy/$nmy/; 
    unless (exists($fh{$code})) { 
     my $fn = "code" . $code . '.csv'; 
     open($fh{$code}, ">", $fn); 
     $justOpened = 1; 
    } 
    select($fh{$code}); 
    if ($justOpened) { 
     print("$header\n"); 
     $justOpened = 0; 
    } 
    print("$line\n"); 
} 
close(INFILE); 
# }}} 

# {{{ close all the filehandles before exiting. 
for my $handle (values(%fh)) { 
    close($handle); 
} 
# }}} 

exit; 
+0

@Miller,你的解决方案绝对是好的,但它涉及在输入的每一行打开(或重新打开)文件。当我必须做类似的事情时,输入数据文件是绝对巨大的(每个10到20 Gb)以及其中几个。那时我才发现打开文件实际上是一个很慢的操作,并且提出了将打开的文件句柄保存为散列值的小方案。它稍微复杂一点,但对我来说明显加快了速度。 – chandra 2014-09-06 13:47:28

+0

你是对的。如果文件很大,那么缓存文件句柄就很有意义,而且相对容易。但是,这确实引入了潜在的问题,即该问题可能需要多少个文件句柄,以及可能需要调整ulimit。鉴于描述,我怀疑大小/速度实际上并不是一个巨大的问题。 – Miller 2014-09-11 00:36:27

0

你的目标描述很清楚。但是,您的代码显得格式不正确。

,而不是试图分析出您的编程是哪里错了,我只是要证明我将如何处理这个问题:

use feature ':5.12'; 
use strict; 
use warnings; 
use autodie; 

my $dataset   = 'R:/dataset/'; 
my $output_directory = 'R:/results/'; 

#open my $infh, '<', "$dataset/CH_dataset.csv"; 
my $infh = \*DATA; 

my $header = <$infh>; 

my %codes =(); 
while (<$infh>) { 
    chomp; 
    my $code = (split ',')[1]; 

    #my $outfile = "$output_directory/CH_${code}_v$version.$update.csv"; 
    my $outfile = "CH_${code}.csv"; 

    my $outfh; 
    if (!-e $outfile) { 
     open $outfh, '>', $outfile; 
     print $outfh $header; 
    } else { 
     open $outfh, '>>', $outfile; 
    } 

    # Remove Day of Month 
    s/\d{2}-(?=(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-\d{2})//g; 

    print $outfh "$_\n"; 
} 

__DATA__ 
Patient,Code,test1,test2,test3 
P1,072,,25-Mar-14,           
P2,072,29-May-14,,           
P3,073,,03-Jan-14,         
P4,074,,,16-Feb-14           
P5,075,,09-Jul-14,           
P6,075,08-Jun-14,, 

输出4个文件:

$ ls CH_07* 
CH_072.csv CH_073.csv CH_074.csv CH_075.csv 

$ cat CH_07* 
Patient,Code,test1,test2,test3 
P1,072,,Mar-14,           
P2,072,May-14,,           
Patient,Code,test1,test2,test3 
P3,073,,Jan-14,         
Patient,Code,test1,test2,test3 
P4,074,,,Feb-14           
Patient,Code,test1,test2,test3 
P5,075,,Jul-14,           
P6,075,Jun-14,,