2017-08-16 16 views
2

由於數據量巨大,我們使用熊貓來處理數據,但出現了一個非常奇怪的現象。僞代碼如下所示:具有塊大小選項的pandas.read_csv函數的奇怪索引機制

reader = pd.read_csv(IN_FILE, chunksize = 1000, engine='c') 
for chunk in reader: 
    result = [] 
    for line in chunk.tolist(): 
     temp = complicated_process(chunk) # this involves a very complicated processing, so here is just a simplified version 
     result.append(temp) 
    chunk['new_series'] = pd.series(result) 
    chunk.to_csv(OUT_TILE, index=False, mode='a') 

我們可以確認每個循環的結果不爲空。但只有在循環的第一次,chunk['new_series'] = pd.series(result)行有結果,其餘都是空的。因此,只有輸出的第一個塊包含new_series,其餘都是空的。

我們錯過了什麼嗎?提前致謝。

回答

3

你應該在你的循環之上聲明result,否則你只是用每個塊重新初始化它。

result = [] 
for chunk in reader: 
    ... 

你以前的方法在功能上等同於:

for chunk in reader: 
    del result # because it is being re-assigned on the following line. 
    result = [] 
    result.append(something) 
print(result) # Only shows result from last chunk in reader (the last loop). 

另外,我建議:

chunk = chunk.assign(new_series=result) # Instead of `chunk['new_series'] = pd.series(result)`. 

我假設你正在做的line可變的東西在你for loop,即使它在上面的示例中沒有使用。

+1

非常感謝。是的,你的建議奏效了。但我不明白爲什麼移動result = []以外的作品。這對我來說很尷尬。你能詳細說一下嗎?非常感謝! – acepor

+0

感謝您的解釋。但這並不是造成問題的原因。當我們追蹤每個塊的索引時,我發現它們不是單獨的。我們假設每個塊都會從0開始索引,但實際上它不是。在這種情況下,每個塊的索引是整個CSV的一個子集,因此它們的索引源自CSV。這是造成問題的原因。在上面的例子中,'pandas.to_csv'只寫入第一個塊的結果,而不是最後一個塊。但我仍然會感謝你的靈感;否則,我真的不知道如何解決這個問題。 – acepor

+0

您是否使用我的'chunk = chunk.assign(new_series = result)'建議?我不認爲你會有這個問題。 – Alexander

1

一個更好的解決辦法是這樣的:

reader = pd.read_csv(IN_FILE, chunksize = 1000, engine='c') 
for chunk in reader: 
    result = [] 
    for line in chunk.tolist(): 
     temp = complicated_process(chunk) # this involves a very complicated processing, so here is just a simplified version 
     result.append(temp) 
    new_chunk = chunk.reset_index() 
    new_chunk = new_chunk.assign(new_series=result) 
    new_chunk.to_csv(OUT_TILE, index=False, mode='a') 

注意:每個塊的指標是不是個人,而是導出整個文件。如果我們從每個循環追加一個新的系列,塊將繼承整個文件的索引。因此,每個塊和新系列的索引不匹配。

@亞歷山大解決方案的工作,但result可能會變得巨大,所以它會佔用太多的內存。

這裏的新解決方案將通過執行new_chunk = chunk.reset_index()來重置每個塊的索引,並且result將在每個循環內重置。這節省了大量的內存。