pandas chunksize -循环内外的concat

gev0vcfq  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(141)

我必须读取大量的csv文件(5亿行),为了减少内存消耗,我尝试使用pandas使用chunksize方法读取它们。但是我不理解concat方法的行为以及读取所有文件和减少内存的选项。我添加了一些伪代码来解释我到目前为止所做的。
假设我正在阅读,然后用以下命令连接一个有n行的文件:

iter_csv = pd.read_csv(file.csv,chunksize=n/2)
df = pd.concat([chunk for chunk in iter_csv])

然后,我必须将一个函数应用于该框架,以基于一些值创建一个新列:

df['newcl'] = df.apply(function)

一切都很好。但是现在我想知道上面的程序和下面的程序有什么区别:

iter_csv = pd.read_csv(file.csv,chunksize=n/2)
for chunk in iter_csv:
    chunk['newcl'] = chunk.apply(function)
    df = pd.concat([chunk])

在RAM消耗方面,我认为第二种方法应该更好,因为它只将函数应用于块,而不是整个块。但会出现以下问题:
1.将df = pd.concat([chunk])放入循环中,返回一个大小为n/2(块的大小)的数组,而不是完整的数组;
1.将df = pd.concat([chunk])放在外面,在循环返回相同的n/2帧长度之后。
因此,我怀疑第一种方法(在read_csv函数之后连接嵌套框架)是否是最好的方法,平衡了速度和RAM消耗。我还想知道如何使用for循环来连接这些块。
谢谢你的支持。

8yoxcaq7

8yoxcaq71#

如果你最终还是把整个数据集放在RAM中,那么分块加载数据有什么意义呢?分块的主要思想-是逐块处理大数据集,而不是将整个文件加载到内存中。
在你的情况下,你可能会保存结果到输出.csv文件结束?所以:

CHUNK_SIZE = 1000000
fheader = 1
fmodes = ('a', 'w')
output_file = 'output.csv'

for chunk in pd.read_csv('file.csv', chunksize=CHUNK_SIZE):
    chunk['newcl'] = chunk.apply(function)  # your processing (assuming no cross-chunk aggregation
    chunk.to_csv(output_file,
                 mode=fmodes[fheader],      # create or append 
                 header=fheader,            # write csv column names
                 index=False)               # do not save dataframe's index 
    fheader = 0                             # reset fheader flag for the rest of chunks

这样,一次只有1个数据块将在存储器中(理论上)。
P.S.在实践中,如果你在处理过程中创建了一些大的tmp_df对象,它们可能会在RAM中积累(内存泄漏)。甚至用del tmp_df显式地清除它们并foring gc.collect()也不总是有帮助。我找到了一个解决方案:在一个单独的子函数中实现处理-做内存清理更好(所有本地函数对象在函数退出时自动清除)。

相关问题