当我合并两个 Pandas 数据帧时出现 MemoryError
Posted
技术标签:
【中文标题】当我合并两个 Pandas 数据帧时出现 MemoryError【英文标题】:MemoryError when I merge two Pandas data frames 【发布时间】:2018-05-03 08:11:13 【问题描述】:我几乎在整个互联网上进行了搜索,但不知何故,这些方法似乎都不适用于我的情况。
我有两个大的 csv 文件(每个都有一百万多行,大小约为 300-400MB)。他们使用 read_csv 函数很好地加载到数据帧中,而无需使用 chunksize 参数。 我什至对这些数据执行了一些小的操作,例如新列生成、过滤等。
但是,当我尝试合并这两个帧时,我得到了 MemoryError。我什至尝试使用 SQLite 来完成合并,但徒劳无功。手术需要很长时间。
我的电脑是 Windows 7 电脑,内存为 8GB。 Python 版本是 2.7
谢谢。
编辑:我也尝试过分块方法。执行此操作时,我没有收到 MemoryError,但 RAM 使用量激增并且我的系统崩溃。
【问题讨论】:
你用什么代码来合并它们? merge_df = pandas.merge(df1, df2, left_on = "Colname1", right_on = "Colname2") 您使用的是 64 位版本的 Python 吗? 是的。我使用的是 64 位 Python 2.7。目前,Anaconda 4.3(带有 Spyder 3)已安装在我的系统上。 你能粘贴每个数据框的前几行吗?很有可能,您正在执行与您预期的操作不同的合并。 (根据我的经验,大多数涉及小于 1GB 的数据帧的连接操作在几秒钟内完成,但这当然取决于连接的类型以及数据的结构。) 【参考方案1】:当您使用 pandas.merge 合并数据时,它将使用 df1 内存、df2 内存和 merge_df 内存。我相信这就是您出现内存错误的原因。您应该将 df2 导出到 csv 文件并使用 chunksize 选项并合并数据。
这可能是一个更好的方法,但你可以试试这个。 *对于大型数据集,您可以在 pandas.read_csv 中使用 chunksize 选项
df1 = pd.read_csv("yourdata.csv")
df2 = pd.read_csv("yourdata2.csv")
df2_key = df2.Colname2
# creating a empty bucket to save result
df_result = pd.DataFrame(columns=(df1.columns.append(df2.columns)).unique())
df_result.to_csv("df3.csv",index_label=False)
# save data which only appear in df1 # sorry I was doing left join here. no need to run below two line.
# df_result = df1[df1.Colname1.isin(df2.Colname2)!=True]
# df_result.to_csv("df3.csv",index_label=False, mode="a")
# deleting df2 to save memory
del(df2)
def preprocess(x):
df2=pd.merge(df1,x, left_on = "Colname1", right_on = "Colname2")
df2.to_csv("df3.csv",mode="a",header=False,index=False)
reader = pd.read_csv("yourdata2.csv", chunksize=1000) # chunksize depends with you colsize
[preprocess(r) for r in reader]
这会将合并的数据保存为 df3。
【讨论】:
是的,如果你想做内部连接,你不需要做 # 保存只出现在 df1 中的数据 df_result = df1[df1.Colname1.isin(df2.Colname2)!=True] df_result. to_csv("df3.csv",index_label=False, mode="a") 我认为创建 df2.csv 文件的语句丢失了。 很抱歉,您只需要使用 chunksize 选项加载“yourdata2.csv” 1.在运行循环之前,您是否使用del(object)释放了所有不必要的对象? 2. 如果是这样,您可以尝试通过几行 df2 和所有行 df1 来做吗?*以防万一您加入正确的行并检查结果是否符合预期。 为什么要赋值 df2_key = df2.Colname2【参考方案2】:@T_cat 建议的一般块版本效果很好。
但是,连接具有Nan
值的列可能会导致内存爆炸。
因此,您可能希望从联接中排除这些行。
见:https://github.com/pandas-dev/pandas/issues/24698#issuecomment-614347153
【讨论】:
【参考方案3】:您收到 MemoryError: Unable to allocate..
的原因可能是由于数据框中的重复或空白。检查您要加入的列(使用合并时),看看您是否有重复或空白。如果是这样,请使用以下命令摆脱它们:
df.drop_duplicates(subset ='column_name', keep = False, inplace = True)
然后重新运行您的 python/pandas 代码。这对我有用。
【讨论】:
不错的一个!一些变体或这对我也有用。我实际上在索引中有重复,因为我必须在上一步中将 ms 时间戳四舍五入到 s。【参考方案4】:也许左边的数据框在合并列中有 NaN,导致最终合并的数据框膨胀。
如果没问题,用零填充左侧数据框中的合并列。
df['left_column'] = df['left_column'].fillna(0)
然后进行合并。看看你得到了什么。
【讨论】:
以上是关于当我合并两个 Pandas 数据帧时出现 MemoryError的主要内容,如果未能解决你的问题,请参考以下文章
在 Spyder 中打开数据帧时出现 KeyError('pandas._libs.interval')
当我合并两个数据帧时,如何防止 Pandas 将我的整数转换为浮点数?