用Python逐行比较两个CSV文件
我现在有一个脚本版本,它通过将两个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 个回答
如果你在使用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
在上面的命令中。
希望这对你有帮助。
我想到了一个方法,就是逐行读取文件,然后计算每一行的md5或SHA1值,最后再比较这些值。如果空格或者其他字符不重要的话,可以在计算之前把它们去掉。
你可以试试这段代码。它会给你一个所有匹配值的集合。
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]。
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
假设这两个文件的行数是一样的,并且你只想比较每一行之间的差异(也就是说,比较第一个文件的第一行和第二个文件的第一行,以此类推),那么下面这样的代码应该可以实现这个目的:
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.