将 csv 文件与 pandas 连接时内存不足

Posted

技术标签:

【中文标题】将 csv 文件与 pandas 连接时内存不足【英文标题】:Running out of memory while joining csv files with pandas 【发布时间】:2020-11-02 20:21:38 【问题描述】:

我正在尝试在 pandas 中合并相对较大的 CSV 文件。 我有一个包含 236 个文件且总大小为 246MB 的文件夹,我正在尝试将它们合并到一个大的 CSV 文件中,每个文件的列重命名为 filename-close/filename-volume,并在 Unix 时间戳上进行索引. 我希望我的数据中存在一些漏洞,因此我必须使用外部连接来合并它们,但运行以下脚本只会使其通过 18 个 CSV 文件,直到它消耗 26GB 的 RAM 并以错误消息终止:

MemoryError: 无法为形状为 (2, 101966219) 和数据类型 float64

这是完整的代码:

import os
import pandas as pd
import math

ppFiles = os.listdir("./preprocessed")
fullDf = None
for f in ppFiles:
    df = pd.read_csv('./preprocessed/' + f)
    df = df.set_index('time')
    pair = f.split('.')[0]
    print("currently adding pair " + pair)
    df[pair + '-close'] = df['close']
    df[pair + '-volume'] = df['volume']
    df = df.drop(columns=["close", "volume"])
    #print(df.head())
    if fullDf is None:
        fullDf = df
    else:
        fullDf = fullDf.join(df, how="outer")
fullDf.to_csv("./preprocessed/0AllTogether.csv")

我有什么方法可以使用 pandas 和最多 ~27GB 的 RAM 来实现这一点,还是我必须编写自己的基于文本的串联?我希望 32gigs 的系统内存足以完成在内存中连接

这是我数据的前几行,所有 csv 文件的格式如下:

time,close,volume
1596549600,22.0,0.5
1596550500,22.0,0.0
1596551400,22.0,0.0
1596552300,23.0,28.0
1596553200,23.0,0.0
1596554100,40.0,206.79499996
1596555000,40.0,30.0
1596555900,24.4,10.033244
1596556800,20.99,24.1
1596557700,22.0,117.9426
1596558600,25.0,6.8823
1596559500,20.0,0.0
1596560400,21.9,7.25
1596561300,22.0,14.85497737
1596562200,22.0,0.0
1596563100,19.0,28.59515365
1596564000,19.0,11.16297118
1596564900,19.0,10.62149454
1596565800,19.0,0.0
1596566700,24.0,125.1021233

【问题讨论】:

连接可能会占用大量内存。 你的意思是什么。通过数据中的漏洞? 我的意思是希望每个数据点之间有 15 分钟(900 秒),但在我分析数据之前(我想在此步骤之后执行此操作,以便我可以一次分析所有内容,而不必对 236 个文件执行此操作)我相当肯定,在收集此数据集的最后几年中存在一些错误,导致数据点未被记录。 【参考方案1】:

您可以执行一些操作来节省资源,例如

在使用pd.read_csv() 时使用dtype 参数指定数据类型 将float64 向下转换为floatint64 向下转换为int 尽可能将object 转换为category

【讨论】:

嗯,沮丧到int/float?那没有意义。很可能,您打算使用 32 位版本。 int/float 在 numpy 上下文中是通用的 没错,我说的是downcast,因为我常用的方法是df['integer_colum'].apply(pd.to_numeric, downcast='integer') 好的,我认为您的措辞方式令人困惑。顺便说一句,你真的不应该在那里使用apply,而应该使用pd.to_numeric(df['my_column'], downcast='integer') 我现在正在保存set_index 步骤并在加载 csv 时使用 32 位数据类型:df = pd.read_csv('./preprocessed/' + f, index_col="time", dtype="time": np.int32, "close": np.float32, "volume": np.float32) 这节省了一点空间,让我继续处理一个文件,因此差异非常小。 @Taxel 是的,正如我所怀疑的那样,问题将出在外连接上,它可能真的是内存密集型的,而且扩展性很差

以上是关于将 csv 文件与 pandas 连接时内存不足的主要内容,如果未能解决你的问题,请参考以下文章

将 CSV 文件与 pandas 连接

Pandas - 导入大小为 4GB 的 CSV 文件时出现内存错误

pandas 中的大而持久的 DataFrame

在 pandas 中加入数据帧时的内存问题(时间索引)

在 Python 中将 CSV 与不同的列合并

有效地读取巨大的 csv 文件?