2014-10-28 15 views
9

Mam setki dużych plików CSV, które chciałbym scalić w jeden. Jednak nie wszystkie pliki CSV zawierają wszystkie kolumny. Dlatego muszę scalić na podstawie nazwy kolumny, a nie pozycji kolumny.Scal CSV w python z różnymi kolumnami

Po prostu, aby było jasne: w połączonym pliku CSV wartości powinny być puste dla komórki pochodzącej z linii, która nie ma kolumny tej komórki.

Nie mogę użyć modułu pandy, ponieważ powoduje to, że brakuje mi pamięci.

Czy istnieje moduł, który może to zrobić, lub jakiś łatwy kod?

Odpowiedz

10

Klasy csv.DictReader i powinny działać dobrze (patrz Python docs). Coś takiego:

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) 

Komentarze z góry:

  1. musisz określić wszystkie możliwe nazwy pól z wyprzedzeniem DictWriter, więc trzeba pętli wszystkich plików CSV dwukrotnie: raz, aby znaleźć wszystkie nagłówki i raz, aby odczytać dane. Nie ma lepszego rozwiązania, ponieważ wszystkie nagłówki muszą być znane, zanim DictWriter może napisać pierwszą linię. Ta część byłaby bardziej wydajna przy użyciu zestawów zamiast list (operator in na liście jest stosunkowo powolny), ale nie zrobi dużej różnicy dla kilkuset nagłówków. Zestawy straciłyby również deterministyczny porządek listy - kolumny byłyby wyświetlane w innej kolejności za każdym razem, gdy uruchamiałbyś kod.
  2. Powyższy kod jest dla Pythona 3, gdzie dziwne rzeczy dzieją się w module CSV bez newline="". Usuń to dla Python 2.
  3. W tym momencie line to dykt o nazwach pól jako kluczach, a dane kolumn jako wartości. Możesz określić, co zrobić z pustymi lub nieznanymi wartościami w konstruktorach DictReader i DictWriter.

W tej metodzie nie powinno zabraknąć pamięci, ponieważ nigdy nie jest załadowany cały plik naraz.

+0

Dzięki! To działa, ale wszystkie wejściowe pliki CSV mają nagłówki i są powtarzane w połączonym pliku z powyższym kodem. Jak upuścić tę linię dla każdego pliku z wyjątkiem pierwszego? –

+0

W rzeczywistości moje kolumny nie są wyrównane w scalonym dokumencie. Próbuję zrozumieć dlaczego. –

+0

223 kolumn w moim out.csv, ale moja długość pola to 368 ...? –

1

Dla tych z nas, którzy korzystają z wersji 2.7, dodaje to dodatkowy wiersz do zapisu w "out.csv". Aby rozwiązać ten problem, po prostu zmień tryb pliku z "w" na "wb".

+0

Co dodaje dodatkowy wiersz? Przyjęta odpowiedź? Jeśli tak, powinien to być komentarz do zaakceptowanej odpowiedzi, a nie osobna odpowiedź sama. – akousmata