我想知道为什么pandas
在重新索引系列时会占用大量内存。
我创建了一个简单的数据集:
a = pd.Series(np.arange(5e7, dtype=np.double))
根据我在Ubuntu上的top
,整个会话大约是820MB。
现在,如果我将其切片以提取前100个元素:
a_sliced = a[:100]
这表明没有增加内存消耗。
相反,如果我将a
重新索引到相同的范围:
a_reindexed = a.reindex(np.arange(100))
我的内存消耗约为1.8GB。还试图用gc.collect
清理没有成功。
我想知道这是否是预期的,如果有一种解决方法可以重新索引大型数据集而不会产生大量内存开销。
我正在使用来自github的pandas
的最新快照。
答案 0 :(得分:2)
Index使用Hashtable将标签映射到位置。您可以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)
答案 1 :(得分:2)
非常小心地设置copy=False
仅供参考。这可能会导致一些奇怪的效果。如果您的数据相对于索引大小(看起来像是这样)很大,则复制索引是“便宜的”。
如果要消除重建索引后关联的内存,请执行以下操作:
s = a_big_series
s2 = s.reindex(....)
仍然使用内存,因为基础数据只是旧数据的视图(取决于你如何切片。它可以是复制,但这是依赖于numpy)。
s2 = s.reindex(....).copy()
del s
这将释放内存