python – 使用pandas read_csv时出现内存错误

问题:

我正在尝试做一些相当简单的事情,将大型csv文件读入pandas数据帧。

data = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2)

代码要么因为MemoryError失败,要么永远不会完成。

任务管理器中的内存使用量停止在506 Mb,并且在5分钟没有变化且没有CPU活动的过程中我停止了它。

我使用的是pandas版本0.11.0。

我知道文件解析器曾经存在内存问题,但根据http://wesmckinney.com/blog/?p=543这应该已修复。

我试图读取的文件是366 Mb,如果我将文件剪切为短(25 Mb),则上面的代码可以正常工作。

还有一个弹出窗口告诉我它无法写入地址0x1e0baf93 …

堆栈跟踪:

Traceback (most recent call last):
  File "F:\QA ALM\Python\new WIM data\new WIM data\new_WIM_data.py", line 25, in
 <module>
    wimdata = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2
)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 401, in parser_f
    return _read(filepath_or_buffer, kwds)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 216, in _read
    return parser.read()
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 643, in read
    df = DataFrame(col_dict, columns=columns, index=index)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 394, in __init__
    mgr = self._init_dict(data, index, columns, dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 525, in _init_dict
    dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 5338, in _arrays_to_mgr
    return create_block_manager_from_arrays(arrays, arr_names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1820, in create_block_manager_from_arrays
    blocks = form_blocks(arrays, names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1872, in form_blocks
    float_blocks = _multi_blockify(float_items, items)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1930, in _multi_blockify
    block_items, values = _stack_arrays(list(tup_block), ref_items, dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1962, in _stack_arrays
    stacked = np.empty(shape, dtype=dtype)
MemoryError
Press any key to continue . . .

一点背景 – 我试图说服人们Python可以像R一样。为此我试图复制一个R脚本

data <- read.table(paste(INPUTDIR,config[i,]$TOEXTRACT,sep=""), HASHEADER, DELIMITER,skip=2,fill=TRUE)

R不仅能够很好地读取上面的文件,它甚至可以在for循环中读取其中的几个文件(然后对数据进行一些处理)。 如果Python对那个大小的文件有问题,我可能正在打一场失败的战斗……

I am trying to do something fairly simple, reading a large csv file into a pandas dataframe.The code either fails with a MemoryError , or just never finishes.Mem usage in the task manager stopped at 506 Mb and after 5 minutes of no change and no CPU activity in the process I stopped it.I am using pandas version 0.11.0.I am aware that there used to be a memory problem with the file parser, but according to http://wesmckinney.com/blog/?p=543 this should have been fixed.The file I am trying to read is 366 Mb, the code above works if I cut the file down to something short (25 Mb).It has also happened that I get a pop up telling me that it can’t write to address 0x1e0baf93…Stacktrace:A bit of background – I am trying to convince people that Python can do the same as R. For this I am trying to replicate an R script that doesR not only manages to read the above file just fine, it even reads several of these files in a for loop (and then does some stuff with the data).If Python does have a problem with files of that size I might be fighting a loosing battle…

解决方案:

方案1:

Windows内存限制

在Windows中使用32位版本时,python会发生很多内存错误。 这是因为32位进程默认只能获得2GB的内存

降低内存使用率的技巧

如果您没有在Windows中使用32位python,但是在阅读csv文件时希望提高内存效率,那么就有一个技巧。

pandas.read_csv功能采用所谓的选项dtype 这让pandas知道你的csv数据中存在哪些类型。

这是如何工作的

默认情况下,pandas会尝试猜测你的csv文件有什么dtypes。 这是一个非常繁重的操作,因为在确定dtype时,它必须将所有原始数据作为对象(字符串)保留在内存中。

假设你的csv看起来像这样:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01

这个例子当然没有读入内存的问题,但它只是一个例子。

如果pandas在没有任何dtype选项的情况下读取上述csv文件,则年龄将作为字符串存储在内存中,直到pandas读取了足够的csv文件行以进行合格猜测。

我认为pandas中的默认值是在猜测dtype之前读取1,000,000行。

通过指定dtype={'age':int}作为.read_csv()的选项,让pandas知道年龄应该被解释为数字。 这可以节省大量内存。

数据损坏的问题

但是,如果您的csv文件已损坏,请执行以下操作:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01
Dennis, 40+, None-Ur-Bz

然后指定dtype={'age':int}将破坏.read_csv()命令,因为它无法将"40+" .read_csv()为int。 因此,请仔细清理您的数据!

在这里,您可以看到当浮点数保存为字符串时,pandas数据帧的内存使用量是如何更高的:

亲自尝试一下

df = pd.DataFrame(pd.np.random.choice(['1.0', '0.6666667', '150000.1'],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 224544 (~224 MB)

df = pd.DataFrame(pd.np.random.choice([1.0, 0.6666667, 150000.1],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 79560 (~79 MB)

方案2:

我有一个相同的内存问题,简单读取大约1 GB的制表符分隔文本文件(超过550万条记录),这解决了内存问题:

df = pd.read_csv(myfile,sep='\t') # didn't work, memory error
df = pd.read_csv(myfile,sep='\t',low_memory=False) # worked fine and in less than 30 seconds

Spyder 3.2.3 Python 2.7.13 64位

方案3:

我在我的Linux机器上使用Pandas并面临许多内存泄漏,只有在从Github克隆后将Pandas升级到最新版本后才能解决。

方案4:

Pandas 0.12.0和NumPy 1.8.0没有错误。

我已设法创建一个大的DataFrame并将其保存到csv文件,然后成功读取它。 请看这里的例子。 该文件的大小为554 Mb(它甚至适用于1.1 Gb文件,耗时更长,生成1.1Gb文件使用频率为30秒)。 虽然我有4Gb的RAM可用。

我的建议是尝试更新熊猫。 其他可能有用的事情是尝试从命令行运行脚本,因为对于R你没有使用Visual Studio(这已在你的问题的评论中提出),因此它有更多的资源可用。

方案5:

我在虚拟机中运行时遇到了这个问题,或者在内存受到严格限制的其他情况下也遇到了这个问题。 它与pandas或numpy或csv无关,但如果您尝试使用更多内存,则会发生这种情况,即使只是在python中也是如此。

你拥有的唯一机会就是你已经尝试过的东西,试着将大件物品变成适合记忆的小块。

如果你曾经问过自己MapReduce是什么,你自己发现…… MapReduce会尝试在很多机器上分配块,你会尝试一个接一个地在一台机器上处理chunke。

您发现块文件的串联可能确实是一个问题,也许这个操作需要一些副本…但最终这可能会让您在当前情况下保存,但如果您的csv稍微大一些你可能会再次撞到那堵墙……

它也可能是,大熊猫是如此聪明,它实际上只是将你的个别数据块加载到内存中,比如连接到一个大的df?

你可以尝试几件事:

  • 不要一次加载所有数据,而是分成几部分
  • 据我所知,hdf5能够自动执行这些块,只加载程序当前工作的部分
  • 看看类型是否正常,字符串’0.111111’需要比浮点数更多的内存
  • 实际上你需要什么,如果地址是一个字符串,你可能不需要它进行数值分析……
  • 数据库可以帮助只访问和加载您实际需要的部分(例如,只有1%的活跃用户)

方案6:

我在阅读大型CSV文件时尝试了chunksize

reader = pd.read_csv(filePath,chunksize=1000000,low_memory=False,header=0)

读取现在是列表。 我们可以迭代reader并写入/附加到新的csv或者可以执行任何操作

for chunk in reader:
    print(newChunk.columns)
    print("Chunk -> File process")
    with open(destination, 'a') as f:
        newChunk.to_csv(f, header=False,sep='\t',index=False)
        print("Chunk appended to the file")

方案7:

虽然这是一个解决方法而不是修复,但我尝试将该CSV转换为JSON(应该是微不足道的)并使用read_json方法 – 我一直在编写并阅读Pandas中相当大的JSON /数据帧(100s of MB)这样没有任何问题。

参考连接:

https://stackoverflow.com/questions/17557074/17557074