比较两个CSV文件并使用Python导出不匹配

时间:2015-08-17 05:52:32

标签: python csv for-loop

作为使用Python的初学者,我再次陷入困境!我有两个CSV文件如下:

CSV1(主列表)

ID    Name    Code.    Prop
12    SAB     1234     ZXC
12    SAB     1236     ZXC
12    SAB     1233     ZXC
12    SAB     1234     ZXC
11    ASN     1234     ABV
16    HGF     1233     AAA
19    MAB     8765     BCT
19    MAB     8754     BCT

CSV2(子集)

ID    Name    Code.    Prop
12    SAB     1234     ZXC
12    SAB     1236     ZXC
12    SAB     1233     ZXC
12    SAB     1234     ZXC
19    MAB     8765     BCT
19    MAB     8754     BCT

我的目标是尝试使用CSV第一列中的值来比较和识别CSV2中不存在的值。

修改 因此,在上面的示例中,应该导出CSV1(主列表)中ID为11和16的行。

要考虑的事情。 ID虽然唯一,但在两个CSV文件中都有多个实例(如上面csv文件中的示例数据所示)。

我在这个网站上经历了一些主题,例如this one。我想要实现的是与此处所要求的完全相反,但我无法理解该线程上的解决方案。

我试图得到一些结果,但无济于事。我附上了我正在使用的代码:

import csv

fOpen1=open('C:\Master.csv')
fOpen2=open('C:\Subset.csv')
fOutput1=open('C:\Untagged.csv', 'wb')


master=csv.reader(fOpen1)
subset=csv.reader(fOpen2)
untagged=csv.writer(fOutput1)


count=0

subsetCopy=list()

header1=master.next()
header2=subset.next()

untagged.writerow(header1)


for row2 in subset:
    subsetCopy.append(row2)


for row1 in master:
    for row2 in subsetCopy:
        if row1[0] != row2[0]:
            count=count+1
            untagged.writerow(row1)

print count

当我运行这个时,我会得到数百万(数)的非常荒谬的结果。奇怪的是我使用了这个完全相同的代码,没有!= (使用==代替)来实现另一个目标,它就像一个魅力。我认为改变平等条件会给我相反的结果。相反,它最终生成一个巨大的csv文件,并没有用。 我也尝试使用字典但后来意识到它可能无法工作,因为两个文件中的记录重复。对我来说,在两个文件中获取特定行的所有实例非常重要。

我哪里错了?欢迎任何建议/意见。

3 个答案:

答案 0 :(得分:3)

你做错了就是在这个循环中 -

for row1 in master:
    for row2 in subsetCopy:
        if row1[0] != row2[0]:
            count=count+1
            untagged.writerow(row1)

对于master中的每一行,它会将id与row2(使用id)进行比较,然后如果它们不相等,则将该行写为未标记。这会导致row1多次写入untagged,与subsetCopy中不相关的行一样多次,这不是您检查row1&#的方式39; s id存在于子集中。

您需要首先遍历subsetCopy中的每一行,然后将其保存在一个集合中,然后将您要检查的内容与该集合进行比较。示例 -

import csv

fOpen1=open('C:\Master.csv')
fOpen2=open('C:\Subset.csv')
fOutput1=open('C:\Untagged.csv', 'wb')

master=csv.reader(fOpen1)
subset=csv.reader(fOpen2)
untagged=csv.writer(fOutput1)

count=0

subsetCopy=set()
header1=master.next()
header2=subset.next()
untagged.writerow(header1)

for row2 in subset:
    subsetCopy.add(row2[0])

for row1 in master:
    if row1[0] not in subsetCopy:
            count=count+1
            untagged.writerow(row1)
print count

答案 1 :(得分:1)

首先,您要使用set,这会使更多更快。

话虽如此,您将文件1的每一行与每行文件2进行比较。如果它们不匹配(常见情况) - 您将它们添加到File file = new File("c:\\file-utf.xml"); InputStream inputStream= new FileInputStream(file); Reader reader = new InputStreamReader(inputStream,"UTF-8"); InputSource is = new InputSource(reader); // is.setEncoding("UTF-8"); -> This line causes error! Content is not allowed in prolog saxParser.parse(is, handler); 列表中。

重要的是要注意,对于任何一行以上的行所有行都有不匹配的行 - 这会导致它们被多次写入结果。

设置操作包含在untagged中,您可以将它们用于自己的利益,特别是差异,描述如下:

  

包含s但不在t

中的元素的新集合

set operations table

以下是需要进行的更改:

使用generator expressionssetsubset中的所有关键元素创建一个集合:

master

找出关键元素的不同之处:

subsetSet = set(s[0] for s in subset)
masterSet = set(m[0] for m in master)

现在使用这些键从master读取时只读取无标记的行:

untagged_keys = subset - master
print untagged_keys

答案 2 :(得分:0)

对于第一部分,即使您在子集中找到master中的一行,您仍会继续将其与其他行进行比较,并将其添加为无标记。

你的for循环应该是:

for row1 in master:
    for row2 in subsetCopy:
        if row1[0] == row2[0]: 
            break
    else:
        count=count+1
        untagged.writerow(row1)

那就是:如果该行在子集中的任何位置都忽略它,并且只有在没有找到它的情况下通过subset2才计算它。