如果第一列匹配,则将行从一个csv追加到另一个

时间:2019-01-25 18:50:08

标签: python csv merge

我有两个具有相同行但不同列的csv文件:

$ cat file1

category,a,b,c,d,e
apple,0,0,0,0,0
bear,1,1,1,1,1

$ cat file2

category,f,g,h,i,j
bear,10,10,10,10,10
apple,5,5,5,5,5

预期输出:

category,a,b,c,d,e,f,g,h,i,j
apple,0,0,0,0,0,5,5,5,5,5
bear,1,1,1,1,1,10,10,10,10,10

file1file2都是无序的,并且具有相同数量的匹配行(〜15000行)。 file1的列数约为1000,而file2的列数约为16000。我使用了以下方法:

import csv

with open ("file1.csv") as f:
    first = {rows[0]:rows[1:] for rows in list(csv.reader(f))}


with open("file2.csv") as f:
    for row in csv.reader(f):
        if row[0] in first:
            first[row[0]].extend(row[1:])

# print(first)
# {'category': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], 'apple': ['0', '0', '0', '0', '0', '5', '5', '5', '5', '5'], 'bear': ['1', '1', '1', '1', '1', '10', '10','10', '10', '10']}

我觉得我已经接近了,但是我似乎无法使用与上述预期输出相同的格式编写first

在旁注中,对文件进行排序然后追加是否有意义?它们具有完全相同的行数和类别数。

1 个答案:

答案 0 :(得分:1)

您非常接近,但是(IIUC)有一些复杂的因素。主要的原因是file_afile_b的长度不同,因此可以安全地假设它们在A列中的类别数量可能是不相交的。也就是说,类别(bear / apple等)可能存在于一个文件中而不存在于另一个文件中。

因此,我正在使用defaultdict。这意味着,如果密钥不存在,则会自动创建一个密钥,并在其中存储一个空列表。如果我们之前曾看到过该密钥,则只需将现有列表扩展到该密钥即可。如果没有,我们将以完全相同的方式对待它,只是扩展存在的 default 空列表。

您可以通过在file_afile_b中放置一个全新的行来进行测试;该代码将正常运行。

此外,通过包装在函数(build_output)中,我们只需要使用with open()...代码一次。如果要添加另一个文件,只需放入output = build_output('file_c.csv', output),它将以相同的方式添加。

最后,我们将第一列用作字典中的键,并将文件中的所有其余值用作“值”。我们需要将它们串联在一起作为一个列表。我们可以使用第一列作为键,然后将整个行与该键相对应存储,但是如果键不出现多次,那么写回去将很困难。取而代之的是,将key括在列表中,然后将其与值列表连接起来,以给出一个可以在一行上编写的列表。

import csv

from collections import defaultdict

output = defaultdict(list)


def build_output(file_name, output_obj):
    with open(file_name) as infile:
        reader_obj = csv.reader(infile)
        for row in reader_obj:
            output_obj[row[0]].extend(row[1:])
    return output_obj


def write_output(output):
    with open('output.csv', 'w', newline='') as outfile:
        writer = csv.writer(outfile)
        for key, value in output.items():
            row = [key] + value
            writer.writerow(row)


output = build_output('file_a.csv', output)
output = build_output('file_b.csv', output)
write_output(output)