比较两个CSV文件并生成第三个

时间:2013-11-27 19:42:41

标签: perl csv comparison

最近我每个月都在工作,我们会与患者进行验证检查。将上个月的验证与当前月份进行比较需要几天时间:

SeptemberVal.CSV

    Gender    MRN     Operation     Consultant  TCI Date  ... ... ...
    Male    738495      CIRC        Dr Yates    05.12.13  ... ... ...
    Female  247586    Cystoscopy    Dr Know     10.12.13  ... ... ...
    Male    617284      Biopsy      Dr Yates    25.12.13  ... ... ...

OctoberVal.CSV

    Gender    MRN     Operation     Consultant  TCI Date  ... ... ...
    Male    491854      Biopsy      Dr Yates    05.12.13  ... ... ...
    Female  247586    Cystoscopy    Dr Know     10.12.13  ... ... ...
    Female  285769      Biopsy      Dr Yates    25.12.13  ... ... ...
    ...     ...         ...         ...         ...       ... ... ...

Output.csv

    Gender    MRN     Operation     Consultant  TCI Date  ... ... ...
    Female  247586    Cystoscopy    Dr Know     10.12.13  ... ... ...
    ...     ...       ...           ...         ...       ... ... ...

我想创建一个perl脚本,比较SeptermberVal.csv和“OctoberVal.csv”的“MRN”列,然后一旦找到匹配项,我希望它从SeptemberVal复制匹配的整行。 CSV并将其粘贴到新文件中。

每个验证表格可能有800名患者,许多人可以从上个月继续进行,所以说下个月我有900名患者可以验证400名患者可能在之前的表格上,其余的都是新的。

这可能与Perl一起使用,如果是这样的话我该怎么办?如果有人有任何示例代码如何执行此操作,我将不胜感激。从长远来看,我想拿起Perl,因为它在工作社区中被广泛使用。

5 个答案:

答案 0 :(得分:0)

*nix: perform set union/intersection/difference of lists有一个perl示例。您必须对其进行调整,以便仅查看MRN列进行测试。

答案 1 :(得分:0)

你应该尝试使用unix命令join

join可以让您:

  • 选择字段分隔符(逗号);
  • 选择用于连接的字段(2);
  • 格式化输出(来自SeptemberVal.CSV的行)

答案 2 :(得分:0)

这里你去 - 这应该很适合你,它也很容易阅读和修改。

#!/usr/bin/perl
################################################################################
# File: ProcessMRNs
# Author: Mark Setchell
# stackoverflow.com/questions/20251625/perl-comparing-two-csv-files-and-producing-a-third
################################################################################
use strict;
use warnings;
use Data::Dumper;

    my $Debug=0;    # Set to 1 for debug output

    # Check user has supplied last month and this month's CSV file
    if($#ARGV !=1){
       print "Usage: $0 <last_monthCSV> <this_monthCSV>\n";
       exit 1;
    }

    # Pick up CSV filenames from parameters
    my $lastmonth=$ARGV[0];
    my $thismonth=$ARGV[1];

    # Hash to keep last month's records in, indexed by MRN
    my %prevMRNs;
    my $header;

    # Open last month's file and read into hash indexed by MRN
    my $MRN;
    open(FH,"<",$lastmonth) or die "Unable to open $lastmonth";
    while(<FH>){
       chomp;               # Remove end of line junk
       (undef,$MRN,undef)=split(" ");   # Extract MRN from line
       # Save table header if this is it
       if($MRN =~ /MRN/){
          $header=$_;
          next;
       }
       print "DEBUG: Read last month MRN:$MRN\n" if $Debug;
       # Save this MRN into our hash of records, indexed by MRNs
       $prevMRNs{$MRN}=$_;
    }
    close FH;

    # Show user what we got from last month's CSV
    print Dumper \%prevMRNs if $Debug;

    # Now open this month's file 
    open(FH,"<",$thismonth) or die "Unable to open $thismonth";
    print "$header\n";
    while(<FH>){
       chomp;               # Remove end of line junk
       (undef,$MRN,undef)=split(" ");   # Extract MRN
       next if $MRN =~ /MRN/;       # Ignore header line
       print "DEBUG: Read current month MRN:$MRN\n" if $Debug;
       # THIS IS THE CRITICAL LINE IN THE WHOLE SCRIPT
       # If we saw this MRN last month, print what we saw
       print "$prevMRNs{$MRN}\n" if defined $prevMRNs{$MRN};
    }
    close FH;

这是没有调试的输出:

    Gender    MRN     Operation     Consultant  TCI Date  ... ... ...
    Female  247586    Cystoscopy    Dr Know     10.12.13  ... ... ...

这是带有debug的输出:

DEBUG: Read last month MRN:738495
DEBUG: Read last month MRN:247586
DEBUG: Read last month MRN:617284
$VAR1 = {
          '247586' => '    Female  247586    Cystoscopy    Dr Know     10.12.13  ... ... ...',
          '617284' => '    Male    617284      Biopsy      Dr Yates    25.12.13  ... ... ...',
          '738495' => '    Male    738495      CIRC        Dr Yates    05.12.13  ... ... ...'
        };
    Gender    MRN     Operation     Consultant  TCI Date  ... ... ...
DEBUG: Read current month MRN:491854
DEBUG: Read current month MRN:247586
    Female  247586    Cystoscopy    Dr Know     10.12.13  ... ... ...
DEBUG: Read current month MRN:285769

假设您将其保存为“ProcessMRNs”,请执行以下操作:

chmod +x ProcessMRNs
./ProcessMRNs september.csv october.csv

如果您希望将输出放入文件而不是屏幕,请将“&gt; output.txt”添加到最后,如下所示:

./ProcessMRNs september.csv october.csv > output.txt

答案 3 :(得分:0)

只是为了好玩,这是另一个(更简单的)答案:

awk 'FNR==NR{a[$2]=$0;next}{if ($2 in a)print a[$2]}' september.csv october.csv

结果:

Gender    MRN     Operation     Consultant  TCI Date  ... ... ...
Female  247586    Cystoscopy    Dr Know     10.12.13  ... ... ...

这与Perl解决方案完全相同,但使用awk的关联数组(如Perl的哈希)以及处理2个输入文件的技巧,即september.csv和october.csv。

“FNR == NR”部分(直到“下一个”)适用于处理第一个文件,并且对于它在该文件中找到的每个记录,它将整个记录($ 0)保存在一个关联数组中(“ a)由MRN索引(字段2或$ 2)。

然后(从“if”开始)它处理第二个文件(october.csv)并说“如果这个MRN(字段2或$ 2)在数组”a“中(从第一次传递到september.csv)然后打印我们在此时使用此MRN找到的任何行。

答案 4 :(得分:0)

你的Perl怎么样?

首先,您应该使用Text::ParseWordsText::CSV之类的内容来阅读文件。这两个文件都处理列文件并处理引号。 Text::CSV是最受欢迎的,但Text::ParseWords附带Perl,因此它始终可用。

每个文件的MRN号码是唯一的吗?如果是这样,您可能希望将其用作数据结构的。您将不得不知道如何在Perl中使用引用,因此如果您不了解Perl引用,请阅读tutorial

将文件的每一行视为由MRN号码键入,并将每一行作为对另一个哈希的引用,其中每列都以该列的名称键入:

$october{738495}->{gender}     = "M";
$october{738495}->{operation}  = "CIRC";
$october{738495}->{consultant} = "Dr Yates";
$october{738495}->{tci_date}   = "05.12.13";

现在,您可以在9月份查看此结构,如果您在10月份拥有相同的MRI,则可以上线:

for my $mri ( sort keys %september ) {
    if ( exists $october{$mri} ) {       # Similar MRI found in September and October
        if ( $september{$mri}->{gender} eq $october{$mri}->{gender}
            and $september{$mri}->{consultant} eq  $september{$mri}->{consultant} 
            ... ) {
            ....
        else {
            ....
        }
    }
}

如果你知道面向对象的Perl,你应该使用它并帮助规范化性别和顾问名称,日期等事项。