【问题标题】:How to merge two csv files?如何合并两个csv文件?
【发布时间】:2013-05-15 11:01:32
【问题描述】:

我有两个这样的 csv 文件

"id","h1","h2","h3", ...
"1","blah","blahla"
"4","bleh","bleah"

我想合并这两个文件,这样如果两个文件中的 id 相同,那么该行的值应该来自第二个文件。如果它们有不同的 id,那么合并后的文件应该包含两行。


有些值有逗号

"54","34,2,3","blah"

【问题讨论】:

  • 文件是按id排序的吗?

标签: python csv


【解决方案1】:
res = {}

a=open('a.csv')
for line in a:
    (id, rest) = line.split(',', 1)
    res[id] = rest
a.close()

b=open('b.csv')
for line in b:
    (id, rest) = line.split(',', 1)
    res[id] = rest
b.close()

c=open('c.csv', 'w')
for id, rest in res.items():
    f.write(id+","+rest)
f.close()

基本上,您使用每一行的第一列作为字典 res 中的键。因为 b.csv 是第二个文件,所以第一个文件 (a.csv) 中已经存在的键将被覆盖。最后在输出文件 c.csv 中再次合并 keyrest

标题行也将取自第二个文件,但我猜这些应该不会有所不同。

编辑:稍微不同的解决方案,合并任意数量的文件并按顺序输出行:

res = {}
files_to_merge = ['a.csv', 'b.csv']
for filename in files_to_merge:
    f=open(filename)
    for line in f:
        (id, rest) = line.split(',', 1)
        if rest[-1] != '\n': #last line may be missing a newline
            rest = rest + '\n'
        res[id] = rest
    f.close()

f=open('c.csv', 'w')
f.write("\"id\","+res["\"id\""])
del res["\"id\""]
for id, rest in sorted(res.iteritems()):
    f.write(id+","+rest)
f.close()

【讨论】:

  • 如果每个文件的id不同会怎样?正如操作所述,两者都应该出现在您正在编写的 csv 中。
  • OP 说,如果两个文件中都有一个 id,那么应该选择第二个文件中的行。如果一个 id 只存在于两个文档之一中,那么它也应该在结果中。这就是这个脚本应该做的。
  • 我现在看到了。很好地使用字典!
  • 请注意,人们倾向于使用csv 模块而不是在',' 上拆分的原因是假设没有引号引起的问题。在这里,ID 似乎是整数,这可能不是问题,但如果 id 是名称,例如"Smith, John",它不起作用。 csv 解决方案适用于这两种情况。
  • @DSM 感谢您指出这一点。实际上,该行中的某些值在其中有逗号,但在 id 列中没有,所以应该仍然有效吗?
【解决方案2】:

保持键顺序,并根据id 保持最后一行,您可以执行以下操作:

import csv
from collections import OrderedDict
from itertools import chain

incsv = [csv.DictReader(open(fname)) for fname in ('/home/jon/tmp/test1.txt', '/home/jon/tmp/test2.txt')]
rows = OrderedDict((row['id'], row) for row in chain.from_iterable(incsv))
for row in rows.itervalues(): # write out to new file or whatever here instead
    print row

【讨论】:

  • 这会打印字典,而不是 csv 文件
  • @siamii 确实......我将“合并文件”的输出留给您,因为您没有明确声明您想要一个 CSV 文件输出 - 只是一个“合并文件”。而且 - 从显示的代码中查看csv 模块并找出DictReader 的相反数字是什么并不难......
【解决方案3】:

Python3

import csv

with open("a.csv") as a:
    fields = next(a)
    D = {k: v for k,*v in csv.reader(a)}

with open("b.csv") as b:
    next(b)
    D.update({k: v for k,*v in csv.reader(b)})

with open("c.csv", "w") as c:
    c.write(fields)
    csv.writer(c, quoting=csv.QUOTE_ALL).writerows([k]+v for k,v in D.items())

【讨论】:

  • 我认为 Python 3 需要 newline=''
猜你喜欢
  • 2019-03-27
  • 2015-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-12
  • 2011-01-26
  • 2013-01-11
  • 1970-01-01
相关资源
最近更新 更多