首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >熊猫记忆管理问题

熊猫记忆管理问题
EN

Stack Overflow用户
提问于 2017-07-26 15:34:39
回答 2查看 707关注 0票数 1

我对Pandas占用太多内存有意见。我有一个5.5gb的文件,其中有2列,我想简单地保存第一列中的所有唯一值,如下所示:

代码语言:javascript
复制
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

代码语言:javascript
复制
Result File
     User
0    12
1    13
2    14
3    15

由于RAM的限制,我将主文件分30块导入,试图从内存中清除数据,每次只追加结果文件。经过两次迭代(30个迭代)后,结果文件为13.5mb。但是在第6次迭代之后,它总是崩溃,我可以在我的流程管理中看到python占用了4.5gb的RAM。我正试着给垃圾收集器打电话,但显然不起作用,你们能帮帮我吗?我的代码如下:

代码语言:javascript
复制
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

从我阅读过的前3行来看,+= 1应该有助于从内存中清除较大的文件。每次迭代之后,我可以看到循环开始时使用的RAM不断增加200 my,在循环期间,每次运行都会增加更多内存。

运行以上代码之前的基本Python使用:76 RAM

循环开始时大约Python RAM的使用情况

代码语言:javascript
复制
0: 300
1: 800
2: 1000
3: 1300

循环结束时Python的近似使用

代码语言:javascript
复制
0: 633
1: 2000
2: 2900
3: 3700

能想象出我在做什么或者假设得不对吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-26 16:49:40

@ypnos给了你一个完美的描述,它应该如何用潘达克的方式来完成。

下面是我对其进行编码的尝试:

生成示例数据并将其写入CSV:

代码语言:javascript
复制
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中我们需要的列:

代码语言:javascript
复制
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'])

结果:

代码语言:javascript
复制
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]
票数 3
EN

Stack Overflow用户

发布于 2017-07-26 16:37:22

您的大文件分割方法效率极低。使用skiprows参数时,读取器需要逐行遍历文件,计数行尾字符,直到所请求的行数通过为止。因此,在最后一次迭代中,在您已经多次处理完大部分文件之后,将再次读取整个文件。

请顺便注意,您对nrows的使用对我来说也是错误的。我希望是nrows=math.ceil(284884514/30)。我相信这就是你记忆问题的原因。

相反,您需要的是一种迭代的方法,可以同时运行文件(),这是由chunksize参数提供的。chunksize的使用在Pandas IO工具文档中得到了很好的说明。

插图代码示例:

代码语言:javascript
复制
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]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45331499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档