【问题标题】:Pandas Merge Two DataFrames results in Memory LeakPandas 合并两个 DataFrame 导致内存泄漏
【发布时间】:2020-12-04 23:45:23
【问题描述】:

问题陈述:

我必须以递归方式对多个 CSV 文件执行 SQL 表连接。 示例:我有文件 CSV1、CSV2、CSV3、.....CSVn

我需要一次在两个 CSV 之间执行连接(内/外/左/全),并与第三个 CSV 连接结果,依此类推,直到所有 CSV 合并。

我的尝试:

我正在使用pandas库合并方法(https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html)来合并CSV文件的数据框。

代码片段:

import pandas as pd
 
df1 = pd.read_csv(path_of_csv1)
df2 = pd.read_csv(path_of_csv2)
resultant_df = df1.merge(df2, left_on='left_csv_column_name', right_on='right_csv_column_name', how='inner')
.....

我使用的是pandas版本1.1.0和python版本3.8.5

我面临的问题:

我正在使用带有8Gb Ram 的 Mac Book Pro,并尝试合并 docker 容器内外的 DataFrame。对于每个大约 10Mb 的较小 CSV 文件,我能够成功合并一些文件,但对于一些较大的 CSV 文件,假设每个 50Mb 我面临内存泄漏问题。在开始合并操作之前,我的系统有 3.5 GB 的可用内存(使用 docker stats <container_name> 检查)分配给 docker,其中 6 GB 并且一旦启动合并过程,docker 就会消耗整个可用 RAM,合并过程在两者之间终止,并以 kill-9信号错误。

我也尝试将它们合并到容器外。同样的内存问题仍然存在,我的进程/终端在两者之间挂起。

PS:如果写错了请见谅。

任何帮助将不胜感激。我完全陷入了这个合并过程。

【问题讨论】:

  • 只是为了澄清:当您尝试合并N csv时出现内存问题,不仅仅是其中2个,对吗?如果是这种情况:您要合并多少个文件?
  • 澄清:即使尝试仅合并两个 CSV 文件,问题仍然存在。
  • 另外:您指定的大小(例如 50Mb)是磁盘上的大小,还是数据框在 pandas 中加载时的大小?如果它是磁盘上文件的大小,您可以尝试估计加载的 pandas.Dataframe 的大小吗?你可以使用df.memory_usage(deep=True),例如this respsonse
  • 所以我指定的大小(大约 50 Mb)是我磁盘中 CSV 的大小。加载数据框时,占用的大小为220688515,使用df.memory_usage(deep=True).sum() 检查。但问题是,我的系统有足够的可用内存来处理这么大的大小,但合并两个数据帧仍会消耗我的整个系统主内存。

标签: pandas dataframe csv merge memory-leaks


【解决方案1】:

你的问题

我认为您没有内存泄漏,但生成的合并数据帧太大而无法放入内存。实际上,memory leak 是指对象没有被系统正确删除(垃圾收集)并累积,导致内存随时间膨胀。

即使您的两个数据框都可以保存在 RAM 中,合并操作也可能导致更大的数据框,从而导致您的内存问题。例如,如果您的合并列中有很多重复值,则可能会发生这种情况:

>>> df1 = pd.DataFrame({'col': ['a', 'a', 'a', 'b']})
>>> df2 = pd.DataFrame({'col': ['a', 'a', 'a', 'c']})
>>> df1.merge(df2, on='col')
  col
0   a
1   a
2   a
3   a
4   a
5   a
6   a
7   a
8   a

我们在结果数据框中有 9 行,这比初始数据框中的总和还要多!那是因为合并操作创建了数据的笛卡尔积(这里:df1的第1行与df的第1、2、3行合并;df1的第2行与第1、2行合并和3等)

现在想象一下最坏的情况,即您的两个合并列中只有 一个值。如果您在每个 df 中说 10^5 行,您最终将得到 10^10 行。这可能是您的问题。

解决方案

要合并无法放入内存或结果太大的数据帧,您可以尝试使用dask 库。请参阅此SO question 的示例答案。

【讨论】:

  • 这是我进一步调试问题的好方向。感谢您的建议。
猜你喜欢
  • 2015-07-06
  • 2014-06-07
  • 2013-11-20
  • 2011-10-28
  • 2016-01-18
  • 2012-12-13
  • 1970-01-01
  • 2011-01-08
  • 2011-02-01
相关资源
最近更新 更多