【问题标题】:Appending rows from one csv to another if their first column matches如果第一列匹配,则将行从一个 csv 附加到另一个
【发布时间】:2019-06-19 15:21:26
【问题描述】:

我有两个行相同但列不同的 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

顺便说一句,对文件进行排序然后追加是否有意义?它们具有完全相同的行数和类别。

【问题讨论】:

    标签: python csv merge


    【解决方案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)
    

    【讨论】:

    • 我的文件具有相同数量的匹配行/类别,所以我认为我的用例不需要 defaultdict。但是非常感谢您的解释!
    • @5areductase defaultdict 的效率同样高,是标准库的一部分,并且可以保护您免受这种情况的影响如果它作为奖励存在:) 你是欢迎解释,如果有什么不清楚的地方请告诉我。
    • @5areductase 道歉,是的,你说他们有不同的列数,而不是行数,我在测试解决方案时忘记了这一点。
    猜你喜欢
    • 2019-07-11
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    相关资源
    最近更新 更多