【问题标题】:Comparing two CSV files and exporting non-matches using Python比较两个 CSV 文件并使用 Python 导出不匹配项
【发布时间】:2023-03-15 14:05:02
【问题描述】:

作为使用 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 文件。 我也尝试使用字典,但后来意识到由于两个文件中的记录重复,它可能无法正常工作。在这两个文件中获取特定行的所有实例对我来说很重要。

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

【问题讨论】:

  • pandas 库对于这类事情非常有用。如果我正确理解您的问题,程序应该输出 ID 为 11 和 16 的行?

标签: python csv for-loop


【解决方案1】:

你做错了什么在这个循环中 -

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

对于master 中的每个 row1,它会将 id 与 row2 进行比较(使用 id ),然后如果它们不相等,则会将该 row1 写入未标记。这将导致row1 被多次写入untagged,与subsetCopy 中不相关的行一样多次,这不是您检查row1 的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

【讨论】:

  • 感谢大家指出for循环中的缺陷。我没有想到。 @Anand-我刚刚尝试了您的方法,但计数错误。只是大声思考,未标记的 csv 和子集中的行数应该等于 master,不是吗?在这种情况下,情况并非如此。有什么想法吗?
  • 那你能拿到多少钱?他们有多远?
  • 主列表 = 8334 子集列表 = 代码中的 7497 个计数 = 968 预期计数 = 837
  • 子集列表中可能有一些行的 id 存在于主列表中,但该行本身不在主列表中,您是否检查过这种可能性。我在代码中没有看到任何问题。甚至子集列表中的某些行在主列表中没有任何 id,或者子集列表中的重复行。
  • 好问题阿南德!不幸的是,我已经完成了一天的工作!星期四之前我不会回来测试。希望那时我能找到你。太感谢了。你知道我是否可以给你发一条私人信息吗?干杯。
【解决方案2】:

首先,您要使用set,这将使这快很多

话虽如此,您将文件 1 的每一行与文件 2 的每一行进行比较。如果它们不匹配(常见情况) - 您将它们添加到 untagged 列表中。

请务必注意,对于任何包含多行的文件,所有行都有不匹配的行 - 这会导致它们被多次写入结果。

集合操作包含在set 中,您可以将它们用于您自己的利益,具体区别如下:

在 s 中但不在 t 中的元素的新集合

以下是需要进行的更改:

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

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

找出关键元素的差异:

untagged_keys = subset - master
print untagged_keys

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

with open('C:\Master.csv') as f:
    master = csv.reader(f)
    untagged = [m for m in master if m and m[0] in untagged_keys]

print untagged

【讨论】:

    【解决方案3】:

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

    你的 for 循环应该是:

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

    也就是说:如果该行在子集中的任何位置,则忽略它,并且仅在您通过子集2而没有找到它时才计算它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-21
      • 1970-01-01
      • 2018-07-21
      • 2016-08-03
      • 1970-01-01
      • 2021-08-07
      相关资源
      最近更新 更多