【问题标题】:Compare few entries based on column in one CSV file against another large CSV - Python根据一个 CSV 文件中的列与另一个大型 CSV 比较几个条目 - Python
【发布时间】:2018-08-30 15:39:42
【问题描述】:

我正在尝试比较 2 个 CSV 文件,其中第一个只有几个条目,另一个有 300 行。如果来自 file1.csv 的列电子邮件与来自 file2.csv 的列电子邮件匹配但日期不匹配,我试图实现的输出是打印大文件中的行输出。我想使用“CSV”模块来做到这一点。这是一个例子:

file1.csv(少数条目):

Tom,Johns,tom.johns@email.com,14 May 2017
Imaginary,User,imaginary@email.com,23 May 2018

file2.csv(大文件):

First,User,first.user@email.com,10 Jan 2018
Second,User,second.user@email.com,13 Feb 2018
Tom,Johns,tom.johns@email.com,16 Jun 2017
Imaginary,User,imaginary@email.com,23 May 2018

result.csv(期望的结果)

Tom,Johns,tom.johns@email.com,16 Jun 2017

我尝试使用函数“next”来实现这一点,但由于 file1.csv 中只有 2 个条目,脚本会停止。我已经重写了代码,但现在我正在对关闭的文件进行 I/O 操作。

import csv

with open('file1.csv', 'r') as first_csv:
    dialect = csv.excel()
    file1 = csv.reader(first_csv, dialect)

with open('file2.csv', 'r') as second_csv:
        dialect = csv.excel()
        file2 = csv.reader(second_csv, dialect)

writer = csv.writer(open('result.csv', 'w'))

output = set()

for row1 in file1:
        for row2 in file2:
                if (row1[2] == row2[2]) and (row1[3] != row1[3]):
                        writer.writerow(row2)
                        output.append(row2)

【问题讨论】:

  • 将每个 csv 文件输入到单独的 SQLite 表中然后加入这些表可能更容易(也更快)。更多阅读:docs.python.org/3/library/sqlite3.htmlsqlite.org/docs.html。 @StefanosGkouts
  • @Mr.Zeus 我对 Python 还是很陌生,所以我仍然对基础知识有所了解。我宁愿使用“import csv”来做,很抱歉没有提到这一点。我已经更新了最初的帖子。
  • 在这种情况下@Python_Rookie,我会用纯 Python 和csv 代码回复你,我只是在做某事。
  • 我刚刚意识到这是因为当你使用withstatement 时,当你到达它的末尾时会关闭 I/O 流。我解决了这个问题,但你的逻辑仍然存在问题。

标签: python-3.x csv


【解决方案1】:

正如@Mr.Zeus 在 cmets 中所说,只要您正在读取或写入 csv 文件,它们就需要保持 open。因此,您不能在此处使用with 语句,它会在退出时关闭文件。

您的代码的另一个问题是(row1[3] != row1[3]) 部分,它始终是False :D

所以这是一个固定版本。请注意finally 块中的close,它确保这将始终发生,即使try 部分中发生异常也是如此。

import csv

first_csv = open('file1.csv', 'r')
second_csv = open('file2.csv', 'r')
output_csv = open('result.csv', 'w')

try:
    file1 = csv.reader(first_csv, csv.excel())
    file2 = csv.reader(second_csv, csv.excel())
    writer = csv.writer(output_csv)

    output = []
    for row1 in file1:
        for row2 in file2:
            if (row1[2] == row2[2]) and (row1[3] != row2[3]):
                writer.writerow(row2)
                output.append(row2)
finally:    
    first_csv.close()
    second_csv.close()
    output_csv.close()

print(output)

【讨论】:

  • 由于某种原因,它只返回[['Tom', 'Johns', 'tom.johns@email.com', '16 Jun 2017']],而它应该返回[['Tom', 'Johns', 'tom.johns@email.com', '16 Jun 2017'], ["Imaginary", "User", "imaginary@email.com", "23 May 2018"]] 当我调整我的代码时也发生了同样的事情,有什么想法吗?
  • 但这就是 OP 所要求的。 (row1[3] != row2[3]) 部分负责 - 删除它,您将获得包含 2 个条目的列表。我只是在这里猜到并把它留在里面。
  • @Jeronimo 你知道为什么代码只打印第一个匹配项而停止查找吗?例如,如果您在 file1 中为“Imaginary User”进行更改(将日期设置为“2018 年 6 月 25 日”),它仍然只会在结果中打印“Tom,Johns,tom.johns@email.com,16 Jun 2017”而不是两条线。
  • @Python_Rookie 嗯,你是对的。这似乎是因为csv阅读器只读取文件一次,所以你基本上不能循环超过一次,这是row2这里的内部循环的情况。 That's related.。我想你必须将数据读入列表并遍历它们。
【解决方案2】:

我设法通过将 CSV 转换为列表来解决此问题。这是最终代码:

import csv

first_csv = open('file1.csv', 'r')
second_csv = open('file2.csv', 'r')
output_csv = open('result.csv', 'w')

file1 = csv.reader(first_csv, csv.excel())
file2 = csv.reader(second_csv, csv.excel())
writer = csv.writer(output_csv)

output = []
list1 = list(file1)
list2 = list(file2)

for row1 in list1:
    for row2 in list2:
        if (row1[2] == row2[2]) and (row1[3] != row2[3]):
            writer.writerow(row2)
            output.append(row2)

first_csv.close()
second_csv.close()
output_csv.close()

print(output)

感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2021-11-28
    • 2020-07-21
    • 2021-05-23
    • 1970-01-01
    相关资源
    最近更新 更多