2016-07-25 16 views
8

Mam pliku csv ~ 50GB, z którymi mam doPrzyspieszenie przetwarzania lekki ~ 50 GB plik CSV

  • potrwać kilka podzbiorów kolumnach CSV
  • Zastosuj inną specyfikację format string do każdy podzbiór kolumn w pliku CSV.
  • Wysyłaj nowy plik CSV dla każdego podzbioru z własną specyfikacją formatu.

Zdecydowałem się użyć Pandy i mają ogólne podejście iteracji nad kawałkami poręcznej bryłkach wielkości (od nieco ponad pół miliona linii) w celu wytworzenia DataFrame i dołączenie części do każdego pliku CSV wyjściowego. Więc coś takiego:

_chunk_size = 630100 

column_mapping = { 
    'first_output_specification' : ['Scen', 'MS', 'Time', 'CCF2', 'ESW10'], 
    # ..... similar mappings for rest of output specifications 
} 
union_of_used_cols = ['Scen', 'MS', 'Time', 'CCF1', 'CCF2', 'VS', 'ESW 0.00397', 'ESW0.08', 
        'ESW0.25', 'ESW1', 'ESW 2', 'ESW3', 'ESW 5', 'ESW7', 'ESW 10', 'ESW12', 
        'ESW 15', 'ESW18', 'ESW 20', 'ESW22', 'ESW 25', 'ESW30', 'ESW 35', 
        'ESW40'] 

chnk_iter = pd.read_csv('my_big_csv.csv', header=0, index_col=False, 
         iterator=True, na_filter=False, usecols=union_of_used_cols) 

cnt = 0 
while cnt < 100: 
    chnk = chnk_iter.get_chunk(_chunk_size) 
    chnk.to_csv('first_output_specification', float_format='%.8f', 
       columns=column_mapping['first_output_specification'], 
       mode='a', 
       header=True, 
       index=False) 
    # ..... do the same thing for the rest of the output specifications 

    cnt += 1 

Mój problem, że jest to naprawdępowolny. Każda porcja trwa około minuty, aby wygenerować dopisek do plików CSV, a więc zajmuję się prawie 2 godzinami, aby zadanie zostało wykonane.

Próbowałem umieścić kilka optymalizacji, używając tylko zjednoczenia podzbiorów kolumn podczas odczytu w pliku CSV, a także ustawienia na_filter=False, ale nadal nie można tego zaakceptować.

Zastanawiam się, czy istnieje szybszy sposób na to przetwarzanie światła pliku CSV w Pythonie, albo za pomocą optymalizacji lub korekty mojego podejścia, albo po prostu istnieje lepsze narzędzie dostosowane do tego rodzaju pracy to Pandas ... dla mnie (niedoświadczony użytkownik Pandy) wygląda na to, że jest tak szybki, jak mógłby dostać się z Pandami, ale mogę się pomylić.

+1

Czy można przełączyć na podejście bazodanowe? To jest jeden duży plik CSV! –

+1

@Jylo Naprawdę chciałbym, żeby tak było, ale nie. –

+0

Czy 'chunksize' zawiera liczbę wierszy, które chcesz mieć w każdym kawałku? – albert

Odpowiedz

6

Nie sądzę, że zyskujesz jakąkolwiek przewagę dzięki ramce danych Pandy, więc po prostu dodajemy narzut. Zamiast tego można użyć python własnego CSV module, który jest łatwy w obsłudze i dobrze zoptymalizowane w C.

Rozważmy czytania znacznie większe kawałki do pamięci (chyba 10MB na raz), a następnie pisanie-out każdy z przeformatowanych podzbiorów kolumn przed przejściem do następnego kawałka. W ten sposób plik wejściowy zostanie tylko raz odczytany i przeanalizowany.

Innym podejściem można spróbować jest Preprocesuj dane z polecenia Unix cut wyodrębnić jedynie odpowiednie kolumny (tak, że Python nie muszą tworzyć obiekty i przydzielić pamięci dla danych w nieużywanych kolumn): cut -d, -f1,3,5 somedata.csv

Na koniec spróbuj uruchomić kod pod numerem PyPy, aby część związana z procesorem skryptu została zoptymalizowana za pomocą JIT śledzenia.

0

Chciałbym spróbować użyć modułu pythona csv i generatorów.

Znalazłem generatory znacznie szybciej niż inne podejścia do analizowania ogromnych dzienników serwera i innych.

import csv 

def reader(csv_filename): 
    with open(csv_filename, 'r') as f: 
     csvreader = csv.reader(f, delimiter=',', quotechar="'") 
     for line in csvreader: 
      yield line # line is a tuple 

def formatter(lines): 
    for line in lines: 
     # format line according to specs 
     yield formatted_line 

def write(lines, csv_filename): 
    with open(csv_filename, 'w') as f: 
     writer = csv.writer(f) 
     for line in lines: 
      writer.writerow(line) 

lines = reader('myfile.in.csv') 
formatted_lines = formatter(lines) 
write(formatted_lines, 'myfile.out.csv') 

To jest tylko do odczytu przekształcania pojedynczego wejścia csv w jeden csv wyjściowego, ale można napisać do formatowania i pisarz wyjściowych kilku plików.

(Teraz widzę, że to pytanie ma już miesiąc - nie jestem pewien, czy rozwiązałeś już swój problem - jeśli nie, i chcesz uzyskać bardziej szczegółowe wyjaśnienia/przykłady, daj mi znać.)

0

Procesor jest szybszy niż dostęp do dysku. Jedna sztuczka polega na zgraniu pliku i przeczytaniu go.

import gzip 

with gzip.open('input.gz','r') as fin: 
    for line in fin: 
     print('got line', line)