合并两个数据帧时的内存问题

问题描述 投票:0回答:4

我对倒数第二句话一无所知。错误是:numpy.core._exceptions.MemoryError:无法为形状为(7791676634)和数据类型为int64的数组分配58.1 GiB

我的想法是,将大约 1200 万条记录的数据框架与另一个包含 3-4 列的数据框架合并应该不是什么大问题。 请帮帮我。完全被困在这里了。谢谢

Select_Emp_df 有大约 900k 条记录 Big_df 有大约 1200 万条记录和 9 列。我只需要合并两个 DF,就像我们在 Excel 中对关键列进行 vlookup 一样。

import pandas as pd

Emp_df = pd.read_csv('New_Employee_df.csv', low_memory = False )

# Append data into one data frame from three csv files of 3 years' 
transactions
df2019 = pd.read_csv('U21_02767G - Customer Trade Info2019.csv', 
low_memory = False )
df2021 = pd.read_csv('U21_02767G - Customer Trade 
Info2021(TillSep).csv', low_memory = False)
df2020 = pd.read_csv('Newdf2020.csv', low_memory = False)

Big_df = pd.concat([df2019, df2020, df2021], ignore_index=True)

Select_Emp_df = Emp_df[['CUSTKEY','GCIF_GENDER_DSC','SEX']]

Big_df = pd.merge(Big_df, Select_Emp_df, on='CUSTKEY')
print (Big_df.info)
python python-3.x
4个回答
1
投票

就在

Big_df = pd.merge(Big_df, Select_Emp_df, on='CUSTKEY') 
之前 尝试删除以前的数据帧。像这样。

del df2019
del df2020
del df2021

这应该节省一些内存

也试试

Select_Emp_df = Emp_df[['CUSTKEY','GCIF_GENDER_DSC','SEX']].drop_duplicates(subset=['CUSTKEY'])


1
投票

年轻时,我使用每个进程可用 RAM 为 32k 到 640k 的机器。我曾经处理过巨大的数据集(呃……几个 Mo,但比内存大得多)。关键是只记住需要的内容。

在这里,您连接了 3 个大型数据帧,以便稍后将其与另一个数据帧合并。如果您遇到内存问题,只需反向连接和合并即可:使用

Emp_df
合并每个单独的文件,并立即将合并的文件写入磁盘,并在每个步骤之间将所有内容从内存中清除。如果您使用 csv 文件,您甚至可以通过将第二个和第三个合并文件附加到第一个文件来直接构建连接的 csv 文件(在
mode='a', header=False
方法中使用
to_csv
)。


0
投票

使用社区提供的建议和我的一些研究,我编辑了我的代码,这对我有用 -

Select_Emp_df['LSTTRDDT'] = pd.to_datetime(Select_Emp_df['LSTTRDDT'],errors = 'coerce') Select_Emp_df = Select_Emp_df.sort_values(by='LSTTRDDT',ascending=True) Select_Emp_df = Select_Emp_df.drop_duplicates(subset='CUSTKEY',keep='last')

我刚刚对上次交易日期的值进行了排序,并删除了

Select_Emp_df
数据框中的重复项(IN CUSTKEY)。


0
投票

另一种方法是手动进行合并。就我而言,一个数据集很大

[9000000, 580]
,另一个数据集很小
[10000, 3]

通常合并的问题是,当合并两个数据帧时,它首先创建第三个数据帧,它是合并的结果,然后将其分配给变量。这意味着有一个时间点,你的记忆需要能够同时保存

df1
df2
以及连接的结果。

因此,如果您有两个数据帧 df1 和 df2 并且合并结果的大小不会缩小那么多,那么当您运行时:

df1 = pd.merge([df1, df2]) 

在合并结果分配回 df1 之前,它位于内存中。为了防止创建额外数据帧的副本,我们可以手动进行连接,这是不推荐的,也不是执行连接的计算效率最高的方法,但它肯定更节省内存:

for col in [columns, that, you, want, to, add, to, df1, from, df2]:
    dict = df2.set_index('joining_column_in_df2')[col].to_dict()
    df1[col] = df1['joining_column_in_df1'].apply(lambda x: labels_dict.get(x))

最后的

df1
就是合并的结果。如果
df2
df1
小得多,这种方法实际上胜过普通合并,因为它跳过了创建另一个巨大数据集和删除原始数据集的开销。

© www.soinside.com 2019 - 2024. All rights reserved.