将 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
向下转换为float
将int64
向下转换为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 连接时内存不足的主要内容,如果未能解决你的问题,请参考以下文章