在Python中合并三个具有相同标头的csv文件

时间:2013-04-22 14:41:07

标签: csv python-3.x header merge

我有多个CSV;但是,我很难合并它们,因为它们都有相同的标题。这是一个例子。

CSV 1:

ID,COUNT
1,3037
2,394
3,141
5,352
7,31

CSV 2:

ID, COUNT
1,375
2,1178
3,1238
5,2907
6,231
7,2469

CSV 3:

ID, COUNT
1,675
2,7178
3,8238
6,431
7,6469

我需要将ID上的所有CSV文件合并,并为每个计数列创建一个包含其他列的新CSV。

我一直用2个CSV测试它,但我仍然没有得到正确的输出。

with open('csv1.csv', 'r') as checkfile: #CSV Data is pulled from
    checkfile_result = {record['ID']: record for record in csv.DictReader(checkfile)}


with   open('csv2.csv', 'r') as infile:
#infile_result = {addCount['COUNT']: addCount for addCount in csv.Dictreader(infile)}
with open('Result.csv', 'w') as outfile:
    reader = csv.DictReader(infile)
    writer = csv.DictWriter(outfile, reader.fieldnames + ['COUNT'])
    writer.writeheader()
    for item in reader:
        record = checkfile_result.get(item['ID'], None)
        if record:
            item['ID'] = record['COUNT']  # ???
            item['COUNT'] = record['COUNT']
        else:
            item['COUNT'] = None
            item['COUNT'] = None
        writer.writerow(item)

但是,使用上面的代码,我得到三列,但第一个CSV中的数据填充在两列中。例如。

Result.CSV *注意跳过CSV中不存在的ID的密钥

ID, COUNT, COUNT
1, 3037, 3037
2, 394, 394
3,141, 141
5,352. 352
7,31, 31

结果应为:

ID, COUNT, COUNT
1,3037, 375
2,394, 1178
3,141, 1238
5,352, 2907
6, ,231
7,31, 2469

Etc等

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

这有效:

import csv

def read_csv(fobj):
    reader = csv.DictReader(fobj, delimiter=',')
    return {line['ID']: line['COUNT'] for line in reader}


with open('csv1.csv') as csv1, open('csv2.csv') as csv2, \
     open('csv3.csv') as csv3, open('out.csv', 'w') as out:
    data = [read_csv(fobj) for fobj in [csv1, csv2, csv3]]
    all_keys = sorted(set(data[0]).union(data[1]).union(data[2]))
    out.write('ID COUNT COUNT COUNT\n')
    for key in all_keys:
        counts = (entry.get(key, '') for entry in data)
        out.write('{}, {}, {}, {}\n'.format(key, *tuple(counts)))

输出文件的内容:

ID, COUNT, COUNT, COUNT
1, 3037, 375, 675
2, 394, 1178, 7178
3, 141, 1238, 8238
5, 352, 2907, 
6, , 231, 431
7, 31, 2469, 6469

详情

函数read_csv返回一个字典,其中id为键,counst为值。我们将使用此函数读取所有三个输入。例如csv1.csv

with open('csv1.csv') as csv1:
    print(read_csv(csv1))

我们得到了这个结果:

{'1': '3037', '3': '141', '2': '394', '5': '352', '7': '31'}

我们需要拥有所有钥匙。一种方法是将它们转换为集合并使用union来查找唯一的集合。我们也对它们进行排序:

all_keys = sorted(set(data[0]).union(data[1]).union(data[2]))

['1', '2', '3', '5', '6', '7']

在所有键的循环中,我们使用entry.get(key, '')检索计数。如果未包含密钥,则会得到一个空字符串。查看输出文件。您只看到逗号,并且在输入中没有找到任何值的值。我们使用生成器表达式,因此我们不必重复键入所有内容三次:

counts = (entry.get(key, '') for entry in data)

这是其中一个发电机的内容:

list(counts)
('3037', '375', '675')

最后,我们写入输出文件。 *将这样的元组('3037','375','675')转换为三个参数,即.format()被调用为.format(key, '3037', '375', '675')

out.write('{}, {}, {}, {}\n'.format(key, *tuple(counts)))