添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
霸气的酸菜鱼  ·  [pandas] DataFrame ...·  1 周前    · 
私奔的领结  ·  Android ...·  1 年前    · 

减少大量数据帧的pandas concat的内存使用量

3 人关注

我有一堆(15,000多个)小数据框,我需要在pandas中逐列串联成一个很大的(100,000x1000)数据框。我有两个(很明显的)担心,速度和内存的使用。

以下是我在Stack Overflow上看到的一个被高度认可的方法。

dfList = [df1, df2, ..., df15000] #made by appending in a for loop
df_out = pd.concat(dfList, axis=1)

这对速度来说是很好的。这是简单的代码,很容易理解。然而,它使用了相当大的内存。我的理解是,Pandas的concat函数是通过建立一个新的大数据框架,然后将所有的信息复制过来,本质上是将程序所消耗的内存翻倍。

我如何避免这种大的内存开销,同时又能将速度降低到最小?

我试着在一个for循环中把列一个一个地添加到第一个df中。对内存来说很好(1+1/15,000),对速度来说很糟糕。

Then I came up with the following. I replace the list with a deque and do concatenation peicewise. It saves memory (4.1GB vs 5.4GB on most recent run), at a manageable speed decrease (<30seconds added here on a 5-6min total length script), but I can't seem to figure out why这样做能节省内存吗?

dfDq = collections.deque()
#add all 15,000 dfs to deque
while(len(dfDq)>2):  
    dfDq.appendleft(pd.concat([dfDq.pop(), dfDq.pop(), dfDq.pop()], axis=1))
if(len(dfDq)==2): df_out = pd.concat([dfDq.pop(), dfDq.pop()], axis=1)
else: df_out=dfDq.pop()

如果我对pd.concat()函数的理解是正确的,这种逐级连接的最后一步应该仍然使用2倍的内存。是什么让这一方法奏效?虽然我上面引用的速度提升和内存节省的数字是针对那一次运行的,但在多次运行中,总体趋势是一样的。

除了试图弄清上述方法的原因外,也愿意接受其他方法的建议。

5 个评论
你的数据需要作为15k pandas数据帧来读取吗?
noah
它以15,000个单独的csv文件开始。我希望能够在每个单独的df上进行处理,但如果有一个重要的论据,我愿意听取它,并有可能重新调整我的代码。目前的运行时间和内存使用情况都很好,所以我基本上只是好奇为什么它能工作。
好吧,不知道为什么它工作得很好,但很高兴知道这可以工作。然而,我有一些其他的提示,也许可以改善你的问题--如果你能负担得起,你可以使用数据类型的下转换来减少原始数据的内存使用。如果你有很多 "对象 "数据类型,特别有用的是将它们转换为分类数据。你可以在连接之前做这件事,并减少整体内存。
如果有用的话,我可以发布更详细的答案。 第二件事是,我相信你已经读过了,这是dask数据框架的主要用例之一,你可以给整个cs列表,并将其视为一个单一的df,并让它在幕后处理这些块。
GZ0
你是否尝试过在 pd.concat 中添加 copy=False 的参数?它有帮助吗?
python
pandas
performance
dataframe
memory
noah
noah
发布于 2019-06-08
1 个回答
John Zwinck
John Zwinck
发布于 2019-06-08
已采纳
0 人赞同

只要提前创建全尺寸的DataFrame。

df = pd.DataFrame(index=pd.RangeIndex(0, N), columns=[...])

Then write to it in sections:

col = 0