Объединение нескольких CSV файлов без повторения заголовков (с использованием Python)
Я начинающий с 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)
Ответы
Ответ 1
Хотя я считаю, что лучшим ответом является метод @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)
Ответ 2
Если вы находитесь в системе 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
Ответ 3
Если вы не против накладных расходов, вы можете использовать pandas, который поставляется с распространенными дистрибутивами python. Если вы планируете делать больше со списками таблиц, я рекомендую использовать 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
, стандартного типа данных в pandas. Если вы конкатенируете несколько из этих dataframes
, он объединяет только файлы данных, если их заголовки одинаковы. Если заголовки не совпадают, он не работает и дает вам ошибку. Вероятно, хорошо, если ваш каталог загрязнен CSV файлами из другого источника.
Другое дело: я добавил sorted()
вокруг interesting_files
. Я предполагаю, что ваши файлы названы по порядку, и этот порядок должен быть сохранен. Я не уверен в glob, но функции os
не обязательно возвращают файлы, отсортированные по их имени.
Ответ 4
Ваш отступ неправильный, вам нужно поместить цикл внутри блока. Вы также можете передать объект файла в 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)
Ответ 5
Ваша попытка почти работает, но проблемы:
- Вы открываете файл для чтения, но закрываете его перед записью строк.
- ты никогда не пишешь название Вы должны написать это один раз
- Также вы должны исключить 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 (или панды тоже) изящно обрабатывает эти случаи.