用Python逐行比较两个CSV文件

0 投票
6 回答
14223 浏览
提问于 2025-04-18 12:01

我现在有一个脚本版本,它通过将两个csv文件一个接一个地读入列表或集合来比较这两个文件。不过,这些csv文件现在太大,无法全部放进内存,所以我想逐行读取,并打印出不同的行。

我不能用两个循环来读取csv文件,因为这样内层的循环会一次性读取整个文件,而外层的循环只会停留在第一行。

我更想这样做,而不是用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)

6 个回答

0

如果你在使用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则表示整行内容。

解释一下:

这里,第一个awk命令会打印file1.csv文件每一行的第一列;第二个awk命令会打印file2.csv文件每一行的第一列。这两个命令的输出会用paste命令并排显示。接下来,这些结果会传给另一个awk命令,在那里,$1是file1.csv的第一列,$2是file2.csv的第一列。然后这两列会进行比较,结果会被打印出来。

如果你想打印行号,可以使用"print NR",其中NR是记录的数量。

同样,你也可以用$2、$3等来比较所有的列。

你还可以用NR<10来比较任意数量的行,这样可以打印前十行的第一列,如下所示:

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

在上面的命令中。

希望这对你有帮助。

0

我想到了一个方法,就是逐行读取文件,然后计算每一行的md5或SHA1值,最后再比较这些值。如果空格或者其他字符不重要的话,可以在计算之前把它们去掉。

1

你可以试试这段代码。它会给你一个所有匹配值的集合。

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)

补充说明:我用的是rows[1],因为我的文件有列标题。如果你用这段代码来比较没有列标题的文件,请使用rows[0]。

1

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
3

假设这两个文件的行数是一样的,并且你只想比较每一行之间的差异(也就是说,比较第一个文件的第一行和第二个文件的第一行,以此类推),那么下面这样的代码应该可以实现这个目的:

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.

撰写回答