Объедините несколько csv-файлов в один

#python #csv

Вопрос:

У меня есть примерно 20 csv-файлов (все с заголовками), которые я хотел бы объединить в 1 csv-файл.

Посмотрев в Интернете, я нашел один из способов-использовать команду терминала:

 cat *.csv > file.csv
 

Это сработало просто отлично, но проблема в том, что, поскольку весь csv-файл поставляется с заголовками, они также помещаются в csv-файл.

Существует ли команда терминала или скрипт python, с помощью которого я могу объединить все эти csv-файлы в один и сохранить только один заголовок?

Огромное спасибо

Комментарии:

1. По какому критерию вы можете определить первый csv-файл, который нам нужен для копирования заголовка, и отличить этот файл от других файлов, с которыми нам нужно объединить первый файл, но игнорировать заголовок? Можете ли вы гарантировать, что все csv-файлы содержат одинаковые столбцы (одинаковые по порядку, имени и номеру)?

Ответ №1:

Мой голос за решение Awk, но поскольку этот вопрос явно касается Python, вот решение для этого.

 import csv
import sys


writer = csv.writer(sys.stdout)

firstfile = True
for file in sys.argv[1:]:
    with open(file, 'r') as rawfile:
        reader = csv.reader(rawfile)
        for idx, row in enumerate(reader):
            # enumerate() is zero-based by defau< 0 is first line
            if idx == 0 and not firstfile:
                continue
            writer.writerow(row)
    firstfile = False
 

Использование: python script.py first.csv second.csv etc.csv >final.csv

Этот простой сценарий не выгоден ни питона, но если вам нужно подсчитать количество полей в нетривиальных CSV-файлов (т. е. со ссылкой на слова поля, которые могут содержать запятые, который не является сепаратор) это сложно в awk, и тривиально в Python (потому что csv библиотека уже точно знает, как справиться с этим).

Комментарии:

1. Это кажется многообещающим. Могу я просто задать вам один вопрос? Это повлияет на строки, как насчет столбца? если в одном из csv-файлов у меня есть лишние столбцы, напишете ли вы это правильно?

2. Он просто слепо копирует ввод в вывод. Если вы хотите принудительно ввести определенное количество столбцов, нетрудно расширить каждую слишком короткую строку ( row.extend([''] * (desired_number_of_fields - len(row))) ), но, возможно, это было бы лучше решить с помощью нового вопроса с правильно прописанными вашими требованиями.

3. большое вам спасибо за потраченное время. Я действительно открыл еще один вопрос об этом

Ответ №2:

Вы можете сделать это с помощью awk :

 awk '(NR == 1) || (FNR > 1)' *.csv > file.csv
 

FNR относится к номеру записи (обычно к номеру строки) в текущем файле и NR относится к общему номеру записи. Таким образом, первая строка первого файла принимается, а первые строки последующих файлов игнорируются.

Это предполагает, что все ваши csv-файлы содержат одинаковое количество столбцов в одном и том же порядке.

Комментарии:

1. У меня есть 2 файла, в которых есть 2 дополнительных столбца. Это приведет к неправильному импорту данных, верно?

2. Это вызовет проблему, ваш лучший вариант, вероятно, использовать панд и небольшой пользовательский скрипт.

3. большое вам спасибо, я так и сделаю. В противном случае я могу просто разделить файлы и объединить их на основе их столбца. Большое спасибо

4. Или слегка расширьте свой сценарий Awk, чтобы добавить пустые столбцы, если в строке ввода слишком мало полей.

5. if (NF<5) { for (i=NF 1; i<=5; i) $i = "" }

Ответ №3:

Эта команда должна работать для вас:

tail -qn 2 *.csv > file.csv

Хотя, обратите внимание, вам нужно иметь дополнительную пустую строку в конце каждого файла, иначе файлы будут объединяться в одной строке 1, 12, 2 , а 1, 1 не в строке 1 и 2, 2 в строке 2.

Комментарии:

1. Эта -q опция поддерживается, например, GNU tail , но не является POSIX.

2. Там нет «дополнительной пустой строки»; файл, который не заканчивается новой строкой, не является допустимым текстовым файлом в POSIX. (Некоторые tail реализации могут добавить новую строку, если ее еще нет; я не думаю, что это связано с предположениями об этом поведении.)