Объединить CSV в Python с разными столбцами

У меня есть сотни больших CSV файлов, которые я хотел бы объединить в один. Однако не все файлы CSV содержат все столбцы. Поэтому мне нужно объединить файлы на основе имени столбца, а не положения столбца.

Просто чтобы прояснить: в объединенном CSV значения должны быть пустыми для ячейки, приходящей из строки, в которой не было столбца этой ячейки.

Я не могу использовать модуль панд, потому что он заставляет меня не хватает памяти.

Есть ли модуль, который может это сделать, или какой-то простой код?

Ответ 1

Классы csv.DictReader и csv.DictWriter должны хорошо работать (см. Документы Python). Что-то вроде этого:

import csv
inputs = ["in1.csv", "in2.csv"]  # etc

# First determine the field names from the top line of each input file
# Comment 1 below
fieldnames = []
for filename in inputs:
  with open(filename, "r", newline="") as f_in:
    reader = csv.reader(f_in)
    headers = next(reader)
    for h in headers:
      if h not in fieldnames:
        fieldnames.append(h)

# Then copy the data
with open("out.csv", "w", newline="") as f_out:   # Comment 2 below
  writer = csv.DictWriter(f_out, fieldnames=fieldnames)
  for filename in inputs:
    with open(filename, "r", newline="") as f_in:
      reader = csv.DictReader(f_in)  # Uses the field names in this file
      for line in reader:
        # Comment 3 below
        writer.writerow(line)

Комментарии выше:

  • Вам нужно указать все возможные имена полей заранее на DictWriter, поэтому вам нужно дважды прокрутить все ваши файлы CSV: один раз, чтобы найти все заголовки и один раз прочитать данные. Нет лучшего решения, потому что все заголовки должны быть известны до того, как DictWriter сможет написать первую строку. Эта часть будет более эффективной с использованием наборов вместо списков (оператор in в списке сравнительно медленный), но это не будет иметь большого значения для нескольких сотен заголовков. Наборы также потеряют детерминированное упорядочение списка - ваши столбцы будут выходить в другом порядке каждый раз, когда вы запускаете код.
  • Вышеприведенный код предназначен для Python 3, где в CSV-модуле происходят странные события без newline="". Удалите это для Python 2.
  • В этот момент line - это dict с именами полей в виде ключей, а данные столбца - значениями. Вы можете указать, что делать с пустым или неизвестным значением в конструкторах DictReader и DictWriter.

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

Ответ 2

Для тех из нас, кто использует 2.7, это добавляет дополнительную строку между записями в "out.csv". Чтобы решить эту проблему, просто измените режим файла с "w" на "wb".