【问题标题】:Compare 2 csv files and output different rows to a 3rd CSV file using Python 2.7使用 Python 2.7 比较 2 个 csv 文件并将不同的行输出到第 3 个 CSV 文件
【发布时间】:2015-09-01 18:11:55
【问题描述】:

我正在尝试比较两个 csv 文件并使用 python 2.7 找到不同的行。当所有列不相同时,行被认为是不同的。这些文件将是具有所有相同列的相同格式,并且将采用这种格式。

oldfile.csv
ID      name     Date          Amount
1       John     6/16/2015     $3000
2       Adam     6/16/2015     $4000

newfile.csv
ID      name     Date          Amount
1       John     6/16/2015     $3000
2       Adam     6/16/2015     $4000
3       Sam      6/17/2015     $5000
4       Dan      6/17/2015     $6000

当我运行我的脚本时,我希望输出只是最后两行并写在一个 csv 文件中,不幸的是我无法让我的代码正常工作。我在下面写的内容会打印出 oldfile.csv 的内容,并且不会打印不同的行。我想要代码做的是在 output.csv 文件中打印出最后一行。即

output.csv
3       Sam      6/17/2015     $5000
4       Dan      6/17/2015     $6000

这是我使用 csv 模块的代码 python 2.7 代码。

import csv

f1 = open ("olddata/olddata.csv")
oldFile1 = csv.reader(f1)
oldList1 = []
for row in oldFile1:
    oldList1.append(row)

f2 = open ("newdata/newdata.csv")
newFile2 = csv.reader(f2)
newList2 = []
for row in newFile2:
    newList2.append(row)

f1.close()
f2.close()

output =  [row for row in oldList1 if row not in newList2]

print output

不幸的是,代码只打印出 oldfile.csv 的内容。我整天都在研究它并尝试不同的变化,但我根本无法让它正常工作。再次,您的帮助将不胜感激。

【问题讨论】:

  • 您的输入在我看来不像 CSV。它是 TSV(制表符分隔值)文件吗?

标签: python python-2.7 csv compare


【解决方案1】:

您当前正在检查旧文件中存在但新文件中不存在的行。那不是你想做的。

相反,您应该检查新文件中存在但不在新文件中的行:

output =  [row for row in newList2 if row not in oldList1]

另外,您的 CSV 文件是 TSV,因此无法正确加载。您应该指示 csv 模块使用 TSV 打开文件。您的代码也可以简化。

这是你可以使用的:

import csv

f1 = open ("olddata/olddata.csv")
oldFile1 = csv.reader(f1, delimiter='\t')
oldList1 = list(oldFile1)

f2 = open ("newdata/newdata.csv")
newFile2 = csv.reader(f2, delimiter='\t')
newList2 = list(newFile2)

f1.close()
f2.close()

output1 =  [row for row in newList2 if row not in oldList1]
output2 =  [row for row in oldList1 if row not in newList2]

print output1 + output2

【讨论】:

  • output = [row for row in newList2 if row not in oldList1 -- 这并不完全正确,因为它忽略了 oldList1 中不在 newlist2 中的行。
  • 更改为您的建议,但现在它只打印出 newList2 中的值。
  • 检查这个简单的例子:A = [1,2,3,4] B = [1,2,5,6] out1 = [row for row in A if row not in B] out2 = [row for row in B if row not in A] print(out1 + out2) #[3, 4, 5, 6]
  • 完美。我现在要打印差异,我正在尝试使用以下代码将输出写入 csv 文件。 with open("out7.csv", "wb") as out: out.write(str(output)) 不幸的是,这会在文件中添加括号和引号。文件内容为[['3,Sam,6/17/2015,"$5,000"'], ['4,Dan,6/17/2015,"$6,000" ']]。我在这里做错了什么?
  • 检查this question,但不要忘记非逗号分隔
【解决方案2】:

如果您的文件看起来像提供的输入,您可以使用集合:

with open("olddata/olddata.csv") as f1, open("newdata/newdata.csv") as f2:
    header = next(f1).split()
    st = set(f1)
    with open("out.csv","w") as out:
        wr = csv.writer(out,delimter="\t")
        # write lines only if they are not in the set of lines from olddata/olddata.csv
        wr.writerows((row.split() for row in f2 if row not in st))

您无需在newdata.csv 中创建行列表,您可以遍历文件对象并随心所欲地编写或执行任何操作。 with 也会自动关闭你的文件。

或者没有 csv 模块,只存储行:

 with open("olddata/olddata.csv") as f1, open("newdata/newdata.csv") as f2:
    header = next(f1)
    st = set(f1)
    with open("out.csv", "w") as out:
        out.writelines((line for line in f2 if line not in st))

输出:

ID      name     Date          Amount
3       Sam      6/17/2015     $5000
4       Dan      6/17/2015     $6000

或者全部使用 csv 模块:

import csv
from itertools import imap
with open("olddata/olddata.csv") as f1, open("newdata/newdata.csv")  f2:
    r1 = csv.reader(f1, delimiter="\t")
    header = next(r1)
    st = set(imap(tuple, r1))
    with open("out.csv", "w") as out:
        wr = csv.writer(out, delimiter="\t")
        r2 = csv.reader(f2, delimiter="\t")
        wr.writerows((row for row in imap(tuple, f2) if row not in st))

如果您不关心顺序并且想要出现在其中但不在两者中的行,您可以使用set.symmetric_difference

import csv
from itertools import imap
with open("olddata/olddata.csv") as f1, open("newdata/newdata.csv")  f2:
    r1 = csv.reader(f1, delimiter="\t")
    header = next(r1)
    st = set(imap(tuple, r1))
    r2 = csv.reader(f2, delimiter="\t")
    print(st.symmetric_difference(imap(tuple, r2)))

输出:

   set([('ID', '', 'name', 'Date', 'Amount'), ('3', 'Sam', '6/17/2015', '$5000'), ('4', 'Dan', '6/17/2015', '$6000')])

排序数据和写入仍然比使用列表更有效。

【讨论】:

  • @benipy,不用担心,对于较小的文件,使用列表很好,但如果您有较大的数据,则一组会更有效率,0(n) vs O(n^2)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 1970-01-01
相关资源
最近更新 更多