Python 比较4个csv文件之间的数据并将其写入单独的输出文件
有人能告诉我如何改进代码吗?我有4个大的csv文件。第一个是一个参考文件,与其他3个文件(file1、file2和file3)进行比较。在这些文件中,有三列。每行为一个单位(例如,ABC、DEF、GHI为3个单独的单位) 我想将file1、file2和file3与参考文件进行比较。如果参考文件中每行的单位出现在所有3个文件中,我想将其写入文件A。如果每行的单位出现在3个文件中的至少1个文件中,则应将其写入文件B。如果每行的单位不出现在任何3个文件中,我想把它们写在文件C中。我目前的策略是将这些文件附加为4个单独的列表,并对它们进行比较。我意识到这种方法是内存密集型的。此外,我的脚本已经运行了很长时间,没有最终输出。因此,我想知道是否有更有效的方法来解决这个问题 下面是我的代码:Python 比较4个csv文件之间的数据并将其写入单独的输出文件,python,csv,comparison,Python,Csv,Comparison,有人能告诉我如何改进代码吗?我有4个大的csv文件。第一个是一个参考文件,与其他3个文件(file1、file2和file3)进行比较。在这些文件中,有三列。每行为一个单位(例如,ABC、DEF、GHI为3个单独的单位) 我想将file1、file2和file3与参考文件进行比较。如果参考文件中每行的单位出现在所有3个文件中,我想将其写入文件A。如果每行的单位出现在3个文件中的至少1个文件中,则应将其写入文件B。如果每行的单位不出现在任何3个文件中,我想把它们写在文件C中。我目前的策略是将这些文
import csv
reference_1 = open ('reference.csv', 'rt', newline = '')
reader = csv.reader(reference_1, delimiter = ',')
file1 = open ('file1.csv','rt', newline = '')
reader1 = csv.reader(file1, delimiter = ',')
file2 = open ('file2.csv', 'rt',newline = '')
reader2 = csv.reader(file2, delimiter = ',')
file3 = open ('file3.csv', 'rt',newline = '')
reader3 = csv.reader(file3, delimiter = ',')
Common = open ('Common.csv', 'w',newline = '')
writer1 = csv.writer(Common, delimiter = ',')
Partial = open ('Partial.csv', 'w',newline = '')
writer2 = csv.writer(Partial, delimiter = ',')
Absent = open ('Absent.csv', 'w',newline = '')
writer3 = csv.writer(Absent, delimiter = ',')
reference = []
fileA = []
fileB = []
fileC = []
for row in reader:
reference.append (row)
for row in reader1:
fileA.append(row)
for row in reader2:
fileB.append(row)
for row in reader3:
fileC.append(row)
for row in reference:
if row in fileA and row in fileB and row in fileC:
writer1.writerow (row)
continue
elif row in fileA or row in fileB or row in fileC:
writer2.writerow (row)
continue
else:
writer3.writerow (row)
reference_1.close()
file1.close()
file2.close()
file3.close()
Common.close()
Partial.close()
Absent.close()
假设行的顺序不重要,并且引用文件中没有重复的行,下面是一个使用的选项
def file_to_set(文件名):
“”“打开一个文件并返回一个包含文件每一行的集合。”“”
打开(文件名)为f时:
返回集(f.read().splitlines(True))
def设置为文件名:
“”“将集合写入文件。”“”
将open(filename,'w')作为f:
f、 笔迹(s)
def比较文件(参考文件名,*文件):
“”“将引用文件与两个或多个文件进行比较。”“”
如果len(文件)<2:
raise TypeError(“比较\u文件至少需要2个文件,得到%s”%
len(文件))
ref=文件到集合(ref文件名)
文件\数据=[文件中f的文件\设置(f)]
all=文件\数据[0]。联合(*文件\数据[1:])
公共=参考交叉点(*文件\数据)
部分=参考交叉点(全部)。差异(公共)
缺席=参考差异(全部)
将_设置为_文件(common,'common.csv')
将_设置为_文件(partial,'partial.csv')
将_设置为_文件(缺席,'缺席.csv')
比较_文件(“reference.csv”、“file1.csv”、“file2.csv”、“file3.csv”)
这个想法是:
all
),包含每个文件(参考文件除外)中的每一行common
),该集合只包含每个文件(包括参考文件)中的行partial
),其中包含参考文件中的行,这些行也至少出现在一个但不是所有其他文件中不存在
),其中只包含引用文件中存在的行普通
、部分
和缺失
写入文件请参阅最终编辑。一个想法是不要使用
csv.reader
,因为您只是在比较行。实际上,您没有单独使用列,因此不要将行拆分。例如,尝试以下一行:reference=reference\u 1.read().splitlines()
。您可以对所有csv.reader
对象执行此操作。然后您也可以删除csv.writer
对象,直接写一行。行/行(而不是列)的顺序重要吗?或者,如果行的顺序发生变化,也可以吗?非常感谢您的建议!非常感谢。只是一个简短的问题。请您解释一下在代码中使用True的价值或重要性:返回集(f.read().splitlines(True))?我不完全理解这种说法。谢谢在每个'\n'
处将字符串拆分为列表,但不会删除'\n'
。如果True
改为False
,则'\n'
字符将被删除。这是True
,因为稍后在代码中调用f.writelines
时,我们需要换行符。不添加行分隔符。
import csv
reference_1 = open ('reference.csv', 'rt', newline = '')
reader = csv.reader(reference_1, delimiter = ',')
file1 = open ('file1.csv','rt', newline = '')
reader1 = csv.reader(file1, delimiter = ',')
file2 = open ('file2.csv', 'rt',newline = '')
reader2 = csv.reader(file2, delimiter = ',')
file3 = open ('file3.csv', 'rt',newline = '')
reader3 = csv.reader(file3, delimiter = ',')
Common = open ('Common.csv', 'w',newline = '')
writer1 = csv.writer(Common, delimiter = ',')
Partial = open ('Partial.csv', 'w',newline = '')
writer2 = csv.writer(Partial, delimiter = ',')
Absent = open ('Absent.csv', 'w',newline = '')
writer3 = csv.writer(Absent, delimiter = ',')
reference = []
fileA = []
fileB = []
fileC = []
for row in reader:
reference.append (row)
for row in reader1:
fileA.append(row)
for row in reader2:
fileB.append(row)
for row in reader3:
fileC.append(row)
for row in reference:
if row in fileA and row in fileB and row in fileC:
writer1.writerow (row)
continue
elif row in fileA or row in fileB or row in fileC:
writer2.writerow (row)
continue
else:
writer3.writerow (row)
reference_1.close()
file1.close()
file2.close()
file3.close()
Common.close()
Partial.close()
Absent.close()
def file_to_set(filename):
"""Opens a file and returns a set containing each line of the file."""
with open(filename) as f:
return set(f.read().splitlines(True))
def set_to_file(s, filename):
"""Writes a set to file."""
with open(filename, 'w') as f:
f.writelines(s)
def compare_files(ref_filename, *files):
"""Compares a reference file to two or more files."""
if len(files) < 2:
raise TypeError("compare_files expected at least 2 files, got %s" %
len(files))
ref = file_to_set(ref_filename)
file_data = [file_to_set(f) for f in files]
all = file_data[0].union(*file_data[1:])
common = ref.intersection(*file_data)
partial = ref.intersection(all).difference(common)
absent = ref.difference(all)
set_to_file(common, 'common.csv')
set_to_file(partial, 'partial.csv')
set_to_file(absent, 'absent.csv')
compare_files('reference.csv', 'file1.csv', 'file2.csv', 'file3.csv')