我遇到了Pandas占用太多内存的问题。我有一个5.5gb的文件,其中包含2列,我想简单地保存第一列中的所有唯一值,如下所示:
Main File
Follower Friend
0 12 260009730
1 12 17568791
2 12 22512883
3 12 15808761
4 12 10135072
5 12 988
6 12 22424855
7 13 9163182
8 14 22990962
9 15 7681662
10 15 17289517
到
Result File
User
0 12
1 13
2 14
3 15
由于RAM限制,我将主文件导入30个部分,尝试从内存中清除数据帧,每次只附加结果文件。经过两次迭代(三十次)后,结果文件为13.5mb。但它在第6次迭代后一直崩溃,我可以在我的进程管理中看到python占用了4.5GB的RAM。我试图打电话给垃圾收集器但显然不能正常工作,你们可以帮帮我吗?我的代码如下:
i = 0
userRelation = pd.DataFrame(columns=['User'])
Location = 'file.txt'
while i < 30:
userRelationHelp = pd.DataFrame(columns=['User'])
print(str(i))
network = pd.read_csv(Location, sep="\t", header=None, encoding='Latin', low_memory=False, skiprows=(i * math.ceil(284884514/30)), nrows=(((i+1) * math.ceil(284884514/30))), names=['Follower', 'Friend'])
userRelationHelp['User'] = network['Follower'].unique()
userRelation = userRelation.append(userRelationHelp)
lst = [userRelationHelp, network]
del lst
gc.collect()
i += 1
从我读过i + = 1之前的最后3行起,应该用来清除内存中较大的文件。在每次迭代之后,我可以看到我在循环开始时使用的RAM不断增加~200mb,并且在循环期间它会逐渐增加每次运行。
在运行上面代码之前使用基本的Python RAM: 76MB
周期开始时的近似Python RAM使用情况
0: 300
1: 800
2: 1000
3: 1300
周期结束时的近似Python RAM使用情况
0: 633
1: 2000
2: 2900
3: 3700
可以想象指出我正在做或假设不正确的事情吗?
答案 0 :(得分:3)
@ypnos gave you a perfect description of how it should be done in Pandaic way.
这是我尝试编写代码:
生成样本数据并将其写入CSV:
fn = r'c:/temp/data.csv'
pd.DataFrame(np.random.randint(1001, 9999, (10**5, 2))) \
.to_csv(fn, sep='\t', index=False, header=None)
仅处理我们需要的CSV中的那些列:
chunksize=10**2 # you may want to use 10**7 as a chunk size
reader = pd.read_csv(fn, sep='\t', usecols=[0], names=['Follower'],
chunksize=chunksize, squeeze=True)
df = pd.DataFrame(np.unique(np.concatenate([ser.unique() for ser in reader])),
columns=['User'])
结果:
In [62]: df
Out[62]:
User
0 1001
1 1002
2 1003
3 1004
4 1005
5 1006
6 1007
7 1008
8 1009
9 1010
... ...
8988 9989
8989 9990
8990 9991
8991 9992
8992 9993
8993 9994
8994 9995
8995 9996
8996 9997
8997 9998
[8998 rows x 1 columns]
答案 1 :(得分:2)
分割大文件的方式非常低效。当您使用skiprows
参数时,阅读器需要逐行浏览文件,计算行结束字符,直到请求的行数已经过去。因此,在最后一次迭代中,整个文件再次读取 之后已经多次查看。
请顺便提一下,您对nrows
的使用对我来说也是错误的。我希望nrows=math.ceil(284884514/30)
。我相信这是你记忆问题的解释。
您需要的是一种迭代方式来运行文件一次,这是由chunksize
参数提供的。 Pandas IO Tools docs中很好地说明了chunksize
的使用情况。
示例性代码示例:
userRelation = pd.DataFrame(columns=['User'])
Location = 'file.txt'
chunksize = math.ceil(284884514/30)
reader = pd.read_csv(Location, sep="\t", header=None, encoding='Latin', low_memory=False, chunksize=chunksize, names=['Follower', 'Friend'])
for network in reader:
userRelationHelp = pd.DataFrame(columns=['User'])
userRelationHelp['User'] = network['Follower'].unique()
userRelation = userRelation.append(userRelationHelp)
lst = [userRelationHelp, network]