合并多个CSV文件而不重复标题(使用Python)

c86crjj0  于 12个月前  发布在  Python
关注(0)|答案(5)|浏览(108)

我是Python的初学者。我有多个CSV文件(超过10个),它们都有相同的列数。我想合并到一个单一的CSV文件,在那里我不会有重复的标题。
因此,从本质上讲,我只需要有第一行的所有标题,从那时起,我需要所有的CSV文件合并的所有行。我该怎么做?
这是我目前为止尝试的。

import glob
import csv


with open('output.csv','wb') as fout:
    wout = csv.writer(fout,delimiter=',') 
    interesting_files = glob.glob("*.csv") 
    for filename in interesting_files: 
        print 'Processing',filename 
    # Open and process file
        h = True
        with open(filename,'rb') as fin:
                fin.next()#skip header
        for line in csv.reader(fin,delimiter=','):
                wout.writerow(line)
myss37ts

myss37ts1#

如果你使用的是Linux系统:

head -1 director/one_file.csv > output.csv   ## writing the header to the final file
tail -n +2  director/*.csv >> output.csv  ## writing the content of all csv starting with second line into final file
wkyowqbh

wkyowqbh2#

虽然我认为最好的答案是来自@valentin的答案,但你可以在不使用csv模块的情况下做到这一点:

import glob

interesting_files = glob.glob("*.csv") 

header_saved = False
with open('output.csv','wb') as fout:
    for filename in interesting_files:
        with open(filename) as fin:
            header = next(fin)
            if not header_saved:
                fout.write(header)
                header_saved = True
            for line in fin:
                fout.write(line)
acruukt9

acruukt93#

如果你不介意开销,你可以使用pandas,它是常见的python发行版附带的。如果您计划使用speadsheet表做更多的事情,我建议您使用pandas,而不是尝试编写自己的库。

import pandas as pd
import glob
interesting_files = glob.glob("*.csv")
df_list = []
for filename in sorted(interesting_files):
    df_list.append(pd.read_csv(filename))
full_df = pd.concat(df_list)

full_df.to_csv('output.csv')

关于Pandas的更多信息。因为它是用来处理类似于电子表格的数据的,所以它知道第一行是标题。当阅读CSV时,它将数据表与头部分离,头部作为dataframe的元数据保存,dataframe是pandas中的标准数据类型。如果你连接几个这样的dataframes,它只连接数据部分,如果它们的头是相同的。如果标题不相同,则失败并给出错误。这可能是一件好事,以防你的目录被其他来源的CSV文件污染。
还有一件事我只是在interesting_files周围添加了sorted()。我假设你的文件是按顺序命名的,这个顺序应该保持下去。我不确定glob,但os函数不一定会返回按名称排序的文件。

g2ieeal7

g2ieeal74#

你的尝试几乎是工作,但问题是:

  • 你正在打开文件进行阅读,但在写入行之前关闭它。
  • 你永远也写不了标题你得写一次
  • 另外,你必须 exclude output.csv从“glob”中,否则输出也在输入中!

下面是正确的代码,直接将csv对象传递给csv.writerows方法,以获得更短更快的代码。也将标题从第一个文件写入输出文件。

import glob
import csv

output_file = 'output.csv'
header_written = False

with open(output_file,'w',newline="") as fout:  # just "wb" in python 2
    wout = csv.writer(fout,delimiter=',')
    # filter out output
    interesting_files = [x for x in glob.glob("*.csv") if x != output_file]
    for filename in interesting_files:
        print('Processing {}'.format(filename))
        with open(filename) as fin:
            cr = csv.reader(fin,delmiter=",")
            header = cr.next() #skip header
            if not header_written:
                wout.writerow(header)
                header_written = True
            wout.writerows(cr)

请注意,使用原始逐行处理的解决方案忽略了重要的一点:如果标题是多行的,他们会失败,拙劣的标题行/重复它的一部分几次,有效地破坏文件。
csv模块(或者pandas)可以很好地处理这些情况。

xfyts7mz

xfyts7mz5#

你的缩进是错误的,你需要把循环放在with块里面。您还可以将文件对象传递给writer.writerows。

import csv
with open('output.csv','wb') as fout:
    wout = csv.writer(fout)
    interesting_files = glob.glob("*.csv")
    for filename in interesting_files:
        print 'Processing',filename
        with open(filename,'rb') as fin:
                next(fin) # skip header
                wout.writerows(fin)

相关问题