2016-07-25 86 views
8

我有與我不得不加快〜50GB CSV的光處理文件

  • 取的CSV
  • 列的幾個子集應用一個不同的格式串說明書中對一個〜50GB csv文件CSV的每個列的子集。
  • 使用自己的格式規範爲每個子集輸出新的CSV。

我選擇使用熊貓,並有遍歷一個方便的塊大小的塊(僅50多萬行)產生一個數據幀,並附加塊到每個輸出CSV的一般方法。因此,像這樣:

_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 

我的問題是,這是真的。每個塊需要大約一分鐘的時間才能生成CSV文件的附加內容,因此我正在尋找將近2個小時完成任務。

我試圖通過在CSV中讀取時僅使用列子集的聯合以及設置na_filter=False來進行一些優化,但它仍然是不可接受的。

我想知道是否有一種更快的方式來對Python中的CSV文件進行這種輕量化處理,無論是通過對我的方法進行優化或修正,還是隻是有一種適合這種工作的更好的工具然後熊貓......給我(一個沒有經驗的熊貓用戶)這看起來像它與熊貓一樣快,但我很可能被誤解了。

+1

是否可以切換到數據庫方式?這是一個大的CSV文件! –

+1

@Jylo我真的希望是這樣,但沒有。 –

+0

'chunksize'是否包含您想要在每個塊中擁有的行數? – albert

回答

6

我不認爲你是從熊貓的數據幀獲得任何優勢,所以它只是增加開銷。相反,你可以使用python自己的CSV module,它易於使用,並且在C中進行了很好的優化。考慮將更大的塊讀入內存(一次可能爲10MB),然後在推進之前寫出每個重新格式化的列子集到下一個塊。這樣,輸入文件只能被讀取和解析一次。其他

一種方法,你可以嘗試是預處理與Unix的cut命令的數據只提取相關的列(使Python沒有創建對象,並在未使用的列數據分配內存):cut -d, -f1,3,5 somedata.csv

最後,嘗試運行PyPy下的代碼,以便腳本的CPU綁定部分通過跟蹤JIT進行優化。

0

我會嘗試使用Python CSV模塊和發電機。

我發現發電機比其他方法解析巨大的服務器日誌,這樣的速度要快得多。

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') 

這僅僅是用於讀取轉換單個輸入CSV到一個輸出CSV,但你可以寫的格式化和作家輸出多個文件。

(我現在看到這個問題已經過去了一個月 - 不知道你是否已經解決了你的問題 - 如果沒有,並且你想要更詳細的解釋/例子,請告訴我。)

0

CPU比磁盤訪問速度快。一個竅門是gzip你的文件並從中讀取。

import gzip 

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