Python 比较4个csv文件之间的数据并将其写入单独的输出文件

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中。我目前的策略是将这些文

有人能告诉我如何改进代码吗?我有4个大的csv文件。第一个是一个参考文件,与其他3个文件(file1、file2和file3)进行比较。在这些文件中,有三列。每行为一个单位(例如,ABC、DEF、GHI为3个单独的单位)

我想将file1、file2和file3与参考文件进行比较。如果参考文件中每行的单位出现在所有3个文件中,我想将其写入文件A。如果每行的单位出现在3个文件中的至少1个文件中,则应将其写入文件B。如果每行的单位不出现在任何3个文件中,我想把它们写在文件C中。我目前的策略是将这些文件附加为4个单独的列表,并对它们进行比较。我意识到这种方法是内存密集型的。此外,我的脚本已经运行了很长时间,没有最终输出。因此,我想知道是否有更有效的方法来解决这个问题

下面是我的代码:

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')