2013-08-06 65 views
1

我想知道爲什麼pandas重新索引一個系列時有大量的內存使用。熊貓內存使用時重新索引

我創建了一個簡單的數據集:

a = pd.Series(np.arange(5e7, dtype=np.double)) 

top在我的Ubuntu,整個會議大約是820MB。

現在,如果I切片此來提取第一100個元素:

a_sliced = a[:100] 

這表明沒有增加的存儲器消耗。

相反,如果我在同一個範圍內重新編制a

a_reindexed = a.reindex(np.arange(100)) 

我得到的約1.8GB內存消耗。試圖與gc.collect清理沒有成功。

我想知道這是否是預期的,以及是否有一個解決方法來重新索引大數據集而沒有顯着的內存開銷。

我正在使用來自github的pandas的最新快照。

+1

'reindex'會默認創建一個副本,因此,如果舊的變量仍然是圍繞你應該得到約一倍的內存使用情況。你有沒有試過將'copy = False'傳遞給'reindex'? –

+0

謝謝,用'copy = False'嘗試過,但沒有任何變化。另外,我認爲「熊貓」創建了重新索引的數據的副本,而不是完整的原始數據集。 –

回答

2

索引使用散列表將標籤映射到位置。您可以通過Series.index._engine.mapping進行檢查。必要時創建此映射。如果該指數is_monotonic,您可以使用asof()

import numpy as np 
import pandas as pd 
idx =["%07d" % x for x in range(int(2e6))] 
a = pd.Series(np.arange(2e6, dtype=np.double), index=idx) 
new_index = ["0000003", "0000020", "000002a"] 

print a.index._engine.mapping # None 
print a.reindex(new_index) 
print a.index._engine.mapping # <pandas.hashtable.PyObjectHashTable object at ...> 

a = pd.Series(np.arange(2e6, dtype=np.double), index=idx) 
print a.asof(new_index) 
print a.index._engine.mapping # None 

如果你想要更多的控制有關不存在的標籤,你可以使用searchsorted()並做邏輯自己:

>>> a.index[a.index.searchsorted(new_index)] 
Index([u'0000003', u'0000020', u'0000030'], dtype=object) 
2

要非常非常小心設置copy=False僅供參考。這可能會導致一些奇怪的影響。如果您的數據相對於索引大小(看起來是這樣)是大的,複製索引是'便宜'。

如果你想消除重建索引後,相關的記憶,做這樣的事情:

s = a_big_series 
s2 = s.reindex(....) 

內存仍然使用,因爲底層的數據只是舊數據的視圖(你如何切片dependening它可能是複製,但這是依賴於numpy)。

s2 = s.reindex(....).copy() 
del s 

這將釋放內存

+1

HYRY的下面的評論是問題 - 重建索引正在創建一個大型的哈希表,除非您採取您列出的方法,否則不會被垃圾收集。我們應該爲熊貓添加一個方法來刪除所有的哈希表。或者其他的東西。 –