我有两个具有相同行但不同列的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
file1
和file2
都是无序的,并且具有相同数量的匹配行(〜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
。
在旁注中,对文件进行排序然后追加是否有意义?它们具有完全相同的行数和类别数。
答案 0 :(得分:1)
您非常接近,但是(IIUC)有一些复杂的因素。主要的原因是file_a
和file_b
的长度不同,因此可以安全地假设它们在A列中的类别数量可能是不相交的。也就是说,类别(bear
/ apple
等)可能存在于一个文件中而不存在于另一个文件中。
因此,我正在使用defaultdict
。这意味着,如果密钥不存在,则会自动创建一个密钥,并在其中存储一个空列表。如果我们之前曾看到过该密钥,则只需将现有列表扩展到该密钥即可。如果没有,我们将以完全相同的方式对待它,只是扩展存在的 default 空列表。
您可以通过在file_a
或file_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)