Pandas 合并两个数据帧导致内存泄漏
Pandas Merge Two DataFrames results in Memory Leak
问题陈述:
我必须对多个 CSV 文件递归执行 SQL table 之类的联接。
示例:我有文件 CSV1、CSV2、CSV3、.....CSVn
我需要一次在两个 CSV 之间执行连接(Inner/Outer/Left/Full),然后将连接结果与第三个 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
我面临的问题:
我将 Mac Book Pro 与 8Gb Ram
一起使用,并尝试合并 docker 容器内外的数据帧。对于每个大约 10Mb 的较小 CSV 文件,我能够成功合并一些文件,但对于一些较大的 CSV 文件,假设每个文件 50Mb,我面临内存泄漏问题。在开始合并操作之前我的系统有 3.5 GB 的可用 ram(用 docker stats <container_name>
检查)分配给 6 GB 中的 docker 并且一旦启动合并过程 docker 就会消耗整个可用 RAM 和合并过程因 kill-9 信号错误而终止。
我也试过在容器外合并它们。同样的内存问题仍然存在,我的 process/terminal 挂在中间。
PS: 写错了请见谅
如有任何帮助,我们将不胜感激。我完全陷入了这个合并过程。
你的问题
我认为您没有内存泄漏,但生成的合并数据帧太大而无法放入内存。事实上,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 library. See for example answers to this SO question.
问题陈述:
我必须对多个 CSV 文件递归执行 SQL table 之类的联接。 示例:我有文件 CSV1、CSV2、CSV3、.....CSVn
我需要一次在两个 CSV 之间执行连接(Inner/Outer/Left/Full),然后将连接结果与第三个 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
我面临的问题:
我将 Mac Book Pro 与 8Gb Ram
一起使用,并尝试合并 docker 容器内外的数据帧。对于每个大约 10Mb 的较小 CSV 文件,我能够成功合并一些文件,但对于一些较大的 CSV 文件,假设每个文件 50Mb,我面临内存泄漏问题。在开始合并操作之前我的系统有 3.5 GB 的可用 ram(用 docker stats <container_name>
检查)分配给 6 GB 中的 docker 并且一旦启动合并过程 docker 就会消耗整个可用 RAM 和合并过程因 kill-9 信号错误而终止。
我也试过在容器外合并它们。同样的内存问题仍然存在,我的 process/terminal 挂在中间。
PS: 写错了请见谅
如有任何帮助,我们将不胜感激。我完全陷入了这个合并过程。
你的问题
我认为您没有内存泄漏,但生成的合并数据帧太大而无法放入内存。事实上,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 library. See for example answers to this SO question.