某个skiprows参数后的pandas内存错误

时间:2016-04-26 20:22:01

标签: python pandas memory

我有一个~1.81GB的CSV文件,行数约为4900行。它只有一列包含38个字符的字符串。

我正在使用Digital Ocean VPS(Ubuntu 12.04.4,Python 2.7,pandas 0.18.0,512MB RAM)上的beforeEach读取此文件。我一次读5000行。但是,它开始在describe("A test suite", function() { beforeEach(function () { $('body').empty(); }); }); 处引发错误。这是我在重新启动的计算机上测试的代码,刚刚启动的Python:

read_csv
skiprows = 2800000

如果我使用>>> pd.read_csv(filename, skiprows=2800000, nrows=5000, header=None) 运行它可以正常工作。如果我尝试Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/ayhan/.conda/envs/swrm/lib/python2.7/site-packages/pandas/io/parsers.py", line 529, in parser_f return _read(filepath_or_buffer, kwds) File "/home/ayhan/.conda/envs/swrm/lib/python2.7/site-packages/pandas/io/parsers.py", line 295, in _read parser = TextFileReader(filepath_or_buffer, **kwds) File "/home/ayhan/.conda/envs/swrm/lib/python2.7/site-packages/pandas/io/parsers.py", line 608, in __init__ self.options, self.engine = self._clean_options(options, engine) File "/home/ayhan/.conda/envs/swrm/lib/python2.7/site-packages/pandas/io/parsers.py", line 731, in _clean_options skiprows = set() if skiprows is None else set(skiprows) MemoryError 它再次引发错误,这很奇怪,因为错误在达到2800000后开始。它在此之前经历了每5000个乘数,没有问题。知道为什么会这样吗?

该代码在我的个人计算机上运行良好:

skiprows=1000000

编辑:

原始循环如下:

skiprows=1500000

它从API查询short_id并将结果附加到文件。但是我在顶部给出的代码片本身就会引发错误。

2 个答案:

答案 0 :(得分:3)

问题是skiprows无法阻止在内存中加载数据,从而导致内存错误。对于您的问题,您必须使用read_csv的{​​{3}}参数,而不是nrows

答案 1 :(得分:3)

Pandas正在使用一种令人费解的内存密集型方式来实现skiprows。在pandas.io.parsers.TextFileReader._clean_options

if com.is_integer(skiprows):
    skiprows = lrange(skiprows)
skiprows = set() if skiprows is None else set(skiprows)

lrange(n)执行list(range(n)),所以这基本上是skiprows = set(list(range(skiprows)))。它正在构建两个巨大的列表和一个集合,每个包含280万个整数!我想他们从没想过人们会试图跳过那么多行。

如果您想要以块的形式读取文件,请使用不同的read_csv值重复调用skiprows是一种低效的方法。您可以传递read_csv一个chunksize选项,然后以块的形式迭代返回的TextFileReader

In [138]: reader = pd.read_table('tmp.sv', sep='|', chunksize=4)

In [139]: reader
Out[139]: <pandas.io.parsers.TextFileReader at 0x121159a50>

In [140]: for chunk in reader:
   .....:     print(chunk)
   .....: 
   Unnamed: 0         0         1         2         3
0           0  0.469112 -0.282863 -1.509059 -1.135632
1           1  1.212112 -0.173215  0.119209 -1.044236
2           2 -0.861849 -2.104569 -0.494929  1.071804
3           3  0.721555 -0.706771 -1.039575  0.271860
   Unnamed: 0         0         1         2         3
0           4 -0.424972  0.567020  0.276232 -1.087401
1           5 -0.673690  0.113648 -1.478427  0.524988
2           6  0.404705  0.577046 -1.715002 -1.039268
3           7 -0.370647 -1.157892 -1.344312  0.844885
   Unnamed: 0         0        1         2         3
0           8  1.075770 -0.10905  1.643563 -1.469388
1           9  0.357021 -0.67460 -1.776904 -0.968914

或传递iterator=True并使用get_chunk获取指定大小的块:

In [141]: reader = pd.read_table('tmp.sv', sep='|', iterator=True)

In [142]: reader.get_chunk(5)
Out[142]: 
   Unnamed: 0         0         1         2         3
0           0  0.469112 -0.282863 -1.509059 -1.135632
1           1  1.212112 -0.173215  0.119209 -1.044236
2           2 -0.861849 -2.104569 -0.494929  1.071804
3           3  0.721555 -0.706771 -1.039575  0.271860
4           4 -0.424972  0.567020  0.276232 -1.087401