【问题标题】:Python Compare two CSV Files line by linePython逐行比较两个CSV文件
【发布时间】:2014-08-24 18:29:15
【问题描述】:

我目前有一个脚本版本,它通过将两个 csv 文件一个接一个地读入列表/集合来比较两个文件。 但是,csv目前对于内存来说太大了,所以我想逐行迭代并打印出不同的行。

我不能执行两个 csvreaders 循环,因为内部循环将读取整个文件,而外部循环将在第一行

我宁愿这样做而不是 diff,这样当行不匹配时我可以打印额外的信息来找出原因

编辑:到目前为止,我做了类似的事情,但 csv 太大而无法一次全部加载到列表中

def readFile(filename,columns):
mylist=[]
    with open(filename,'rb') as f:
                reader = csv.reader(f)
                for line in reader:
                    mylist.append(tuple(line[i] for i in columns))
    return mylist

mylist1=readFile(filename1,columns)
mylist2=readFile(filename2,columns)
diff1=diff(mylist1,mylist2)
diff2=diff(mylist2,mylist2)

【问题讨论】:

  • 很好。到目前为止,您尝试过什么?
  • 我在上面举了一个例子

标签: python csv diff with-statement


【解决方案1】:

假设文件的行数相同,并且您只寻找行内差异(即,将第一个文件中的第 1 行与第二个文件中的第 1 行进行比较,依此类推)应该这样工作:

with open(filename1, 'rb') as f1, open(filename2, 'rb') as f2

  rdr1 = CsvReader(f1)
  rdr2 = CsvReader(f2)

  for file1_line in rdr1:

     file2_line = rdr2.next()

     # Perform your comparison between file1_line and file2_line here
     # and print differences, or accumulate only the differences in a 
     # results list.

【讨论】:

  • 这看起来像我要找的东西,谢谢!现在将进行测试
【解决方案2】:

itertools.izip()优雅地解决了这个问题:

import csv
import itertools

reader1 = csv.reader(filename1)
reader2 = csv.reader(filename2)

for lhs, rhs in itertools.izip(reader1, reader2):
    if lhs != rhs:
        print "difference:", lhs, rhs

【讨论】:

  • itertools.izip 不是更节省内存吗?
  • OP 是(大概)使用 Python 2,所以 zip 将耗尽两个迭代器并将两个文件读入内存。为避免这种情况,我们需要使用itertools.izip
  • 这里的实际读数在哪里。它是一次读取整个文件吗?
  • @user3752900 文件读取将在csv.reader() 内发生,但它会返回一个迭代器,该迭代器将在请求时读取文件。这意味着我们永远不会在每个文件中存储超过一行(或多或少)。
  • 我明白了,好的,我也试试这个
【解决方案3】:

你可以试试这个代码。为您提供一组所有匹配值。

import csv

result_path   = 'result_check.csv'
result_file = open(result_path,'r')
result_reader = csv.reader(result_file)

f1 = {}
for rows in result_reader:
    f1[rows[0]] = rows[1]


forest_path = 'pandababy3.csv'
forest_file = open(forest_path, 'r')
forest_reader = csv.reader(forest_file)

f2 = {}
for rows in forest_reader:
    f2[rows[0]] = rows[1]

x = len(set(f1.items()).intersection(set(f2.items())))

print(x)

编辑: 我正在使用行 [1],因为我的文件有列标题。任何人使用此代码比较文件,没有列标题,请使用 rows[0]。

【讨论】:

    【解决方案4】:

    我想到了一种逐行读取文件并应用 md5sum/SHA1 总和然后比较这些值的方法。如果空格或任何其他字符无关紧要,请在应用校验和之前将其删除

    【讨论】:

    • 这可能有效,但如果问题是我错误地输出了这些文件之一,我将无法判断哪些列不匹配以及有什么区别
    • 你可以有一个 (checksum_value, line_number) 的列表而不是只有校验和的列表,然后你可以再次读取文件(完成比较后)并保存不匹配的行以便稍后打印。
    【解决方案5】:

    如果您使用的是 Linux 机器,您可以使用“awk”轻松完成此操作。

    paste <(awk -F, '{ print $1;next } file1.csv ) <(awk -F, '{print $1;next } file2.csv) | awk '{ if ($1==$2) print "match" ; else print "mismatch" }'
    

    $1 表示第一个字段,$2 表示第二个字段,依此类推。 $0 代表整行。

    解释:

    file1.csv 每一行中的字段 1 由第一个 awk 命令打印; file2.csv 每一行中的字段 1 由第二个 awk 命令打印。这些命令的输出使用粘贴命令并排打印。现在这被传送到另一个 awk 命令,其中 $1 是 file1.csv 中的 field1,$2 是 file2.csv 中的第一个字段。然后将这两者进行比较并打印结果。

    如果您想打印行号,可以使用“print NR”,其中 NR 是记录数。

    同样,您可以使用 $2 $3 等来比较所有字段

    您还可以使用 NR

    awk -F, 'NR<=10{print $1}' file1.csv
    

    在上面的命令中。

    希望对您有所帮助。

    【讨论】:

      【解决方案6】:

      以下代码遍历每一行并给出行号以及不同条目的位置和项目作为输出。如果行有很多项目,则此解决方案(python3)很方便,假设使用逗号作为分隔符。

      def compare_csv(file_1, file_2):
      
      with open(file_1, 'r') as csv_1:
          with open(file_2, 'r') as csv_2:
              reader1 = csv.reader(csv_1, delimiter=',')
              reader2 = csv.reader(csv_2, delimiter=',')
              try:
                  i_line = 0
                  while True:
                      row_1 = next(reader1)
                      row_2 = next(reader2)
                      i_line += 1
                      if row_1 != row_2:
                          for k, item in enumerate(row_1):
                              if item != row_2[k]:
                                  print(f"difference Line {i_line}: ")
                                  print(f"item {k}: {row_1[k]}")
                                  print(f"item {k}: {row_2[k]}")
              except StopIteration:
                  print("line numbers differ!")
              finally:
                  print(f"lines parsed = {i_line}")
      

      【讨论】:

        猜你喜欢
        • 2021-04-27
        • 1970-01-01
        • 1970-01-01
        • 2015-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-01
        相关资源
        最近更新 更多