【问题标题】:Script to find duplicates in a csv file用于在 csv 文件中查找重复项的脚本
【发布时间】:2011-05-04 23:26:15
【问题描述】:

我有一个 40 MB 的 csv 文件,其中包含 50,000 条记录。它是一个巨大的产品列表。每行有近 20 个字段。 [商品编号、UPC、描述等]

我该怎么做,

a) 查找并打印重复的行。 [这个文件是一个大的附加文件,所以我需要删除文件中包含的多个标题,所以我想知道首先重复的确切行。]

b) 根据列查找和打印重复行。 [查看是否将 UPC 分配给多个产品]

我需要在服务器上运行命令或脚本,并且安装了 Perl 和 Python。甚至 bash 脚本或命令也适用于我。

我不需要保留行的顺序。等等

我试过了,

排序大文件.csv | uniq -d

得到重复,但我没有得到预期的答案。

理想情况下,我想要 bash 脚本或命令,但如果有人有任何其他建议,那也很好。

谢谢


在 Stack Overflow 上查看:Remove duplicate rows from a large file in Python

【问题讨论】:

  • 为什么uniq -d 没有给你预期的答案?
  • 您应该显示一些示例数据(必要时进行清理),包括您认为重复和非重复的数据。具体来说,如果第一个字段 (item#) 不同,但第二个字段 (UPC) 相同,或者整个记录相同,等等。您还应该更具体地说明“我没有得到预期的答案” “ 方法。 uniq 只查看整行,除非您告诉它跳过该行的一部分(但它不使用逗号作为字段分隔符)。此外,CSV 文件可能很难处理,除非您使用为此目的而制作的工具(例如 Python 库)。

标签: bash python perl


【解决方案1】:

尝试以下方法:

# Sort before using the uniq command
sort largefile.csv | sort | uniq -d

uniq 是一个非常基本的命令,只报告彼此相邻的唯一性/重复。

【讨论】:

  • 你有两次排序。
  • 我在这里也尝试过 perl 版本,并且比这个更快,至少在 windows10 上的 ubuntu shell 中。但两者都工作得很好
【解决方案2】:

在 Perl 中查找并打印重复的行:

perl -ne 'print if $SEEN{$_}++' < input-file

在 Perl 中查找并打印具有重复列的行——比如 where 字段用逗号分隔的第 5 列:

perl -F/,/ -ane 'print if $SEEN{$F[4]}++' < input-file

【讨论】:

  • 值得注意的是,当且仅当 CSV 数据从不包含带引号的分隔符 1,2,"3,3",4 时,后者才有效。
  • @mob:似乎对于任何一组重复的行,最后一行都没有用这个例子打印出来。
【解决方案3】:

您可以使用 SQLite shell 导入您的 csv 文件并创建索引以更快地执行 SQL 命令。

【讨论】:

    【解决方案4】:

    这是我的(非常简单的)脚本,用 Ruby 和 Rake Gem 来完成。

    首先创建一个RakeFile并写下这段代码:

    namespace :csv do
      desc "find duplicates from CSV file on given column"
      task :double, [:file, :column] do |t, args|
        args.with_defaults(column: 0)
        values = []
        index  = args.column.to_i
        # parse given file row by row
        File.open(args.file, "r").each_slice(1) do |line|
          # get value of the given column
          values << line.first.split(';')[index]
        end
        # compare length with & without uniq method 
        puts values.uniq.length == values.length ? "File does not contain duplicates" : "File contains duplicates"
      end
    end
    

    然后在第一列使用它

    $ rake csv:double["2017.04.07-Export.csv"] 
    File does not contain duplicates
    

    并在第二次使用它(例如)

    $ rake csv:double["2017.04.07-Export.csv",1] 
    File contains duplicates
    

    【讨论】:

      【解决方案5】:

      对于第二部分:将带有 Text::CSV 的文件读入以您的唯一键为键的散列中,在添加之前检查散列值是否存在。像这样的:

      数据(不需要排序),在这个例子中我们需要前两列是唯一的:

      1142,X426,Name1,Thing1
      1142,X426,Name2,Thing2
      1142,X426,Name3,Thing3
      1142,X426,Name4,Thing4
      1144,X427,Name5,Thing5
      1144,X427,Name6,Thing6
      1144,X427,Name7,Thing7
      1144,X427,Name8,Thing8
      

      代码:

      use strict;
      use warnings;
      use Text::CSV;
      
      my %data;
      my %dupes;
      my @rows;
      my $csv = Text::CSV->new ()
                              or die "Cannot use CSV: ".Text::CSV->error_diag ();
      
      open my $fh, "<", "data.csv" or die "data.csv: $!";
      while ( my $row = $csv->getline( $fh ) ) {
          # insert row into row list  
          push @rows, $row;
          # join the unique keys with the
          # perl 'multidimensional array emulation' 
          # subscript  character
          my $key = join( $;, @{$row}[0,1] ); 
          # if it was just one field, just use
          # my $key = $row->[$keyfieldindex];
          # if you were checking for full line duplicates (header lines):
          # my $key = join($;, @$row);
          # if %data has an entry for the record, add it to dupes
          if (exists $data{$key}) { # duplicate 
              # if it isn't already duplicated
              # add this row and the original 
              if (not exists $dupes{$key}) {
                  push @{$dupes{$key}}, $data{$key};
              }
              # add the duplicate row
              push @{$dupes{$key}}, $row;
          } else {
              $data{ $key } = $row;
          }
      }
      
      $csv->eof or $csv->error_diag();
      close $fh;
      # print out duplicates:
      warn "Duplicate Values:\n";
      warn "-----------------\n";
      foreach my $key (keys %dupes) {
          my @keys = split($;, $key);
          warn "Key: @keys\n";
          foreach my $dupe (@{$dupes{$key}}) {
              warn "\tData: @$dupe\n";
          }
      }
      

      打印出如下内容:

      Duplicate Values:
      -----------------
      Key: 1142 X426
          Data: 1142 X426 Name1 Thing1
          Data: 1142 X426 Name2 Thing2
          Data: 1142 X426 Name3 Thing3
          Data: 1142 X426 Name4 Thing4
      Key: 1144 X427
          Data: 1144 X427 Name5 Thing5
          Data: 1144 X427 Name6 Thing6
          Data: 1144 X427 Name7 Thing7
          Data: 1144 X427 Name8 Thing8
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-28
        • 1970-01-01
        • 2019-06-25
        • 2013-07-24
        相关资源
        最近更新 更多