减少大量数据帧的熊猫连接内存使用量



我有一堆(15,000+)小数据帧,我需要按列连接,以在熊猫中创建一个非常大(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),速度很糟糕。

然后我想出了以下内容。我用deque替换列表并逐个连接。它节省了内存(4.1GB 与最近运行的 5.4GB),速度下降可控(<在 _x0035_-5=" 分钟的总长度脚本上增加了=" _x0033_0=">为什么这会节省内存?

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倍的内存。是什么使这项工作?虽然我上面引用的有关速度提高和节省内存的数字特定于那一次运行,但多次运行的总体趋势是相同的。

除了试图弄清楚为什么上述有效之外,还对其他方法论建议持开放态度。

只需提前创建完整大小的数据帧:

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

然后分部分写信:

col = 0
for path in paths:
part = pd.read_csv(path)
df.iloc[:,col:col+part.shape[1]] = part
col += part.shape[1]

最新更新