87

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

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

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

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

我正在使用熊猫版本 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 确实对这种大小的文件有问题,我可能正在打一场失败的战斗......

4

8 回答 8

32

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()will 让 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+"转换为 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)
于 2015-07-21T14:14:02.710 回答
5

我在简单读取大约 1 GB 的制表符分隔文本文件(超过 550 万条记录)时遇到了同样的内存问题,这解决了内存问题:</p>

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位

于 2017-11-10T20:00:10.117 回答
3

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

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")
于 2019-03-04T09:30:44.970 回答
2

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

于 2015-03-10T08:13:01.673 回答
1

当我在虚拟机中运行时,或者在内存受到严格限制的其他地方运行时,我也遇到了这个问题。它与 pandas 或 numpy 或 csv 无关,但如果你尝试使用更多的内存,因为你被允许使用,它总是会发生,甚至不仅仅是在 python 中。

你唯一的机会就是你已经尝试过的,试着把大的东西切成适合记忆的小块。

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

您通过块文件的连接发现的内容可能确实是一个问题,也许此操作需要一些副本......但最终这可能会在您当前的情况下节省您,但如果您的 csv 变得更大一点你可能会再次撞到那堵墙...

也可能是,pandas 非常聪明,如果你对它做一些事情,它实际上只会将单个数据块加载到内存中,比如连接到一个大的 df?

您可以尝试几件事:

  • 不要一次加载所有数据,而是分成几部分
  • 据我所知,hdf5 能够自动执行这些块,并且只加载您的程序当前正在处理的部分
  • 查看类型是否正常,字符串 '0.111111' 需要比浮点数更多的内存
  • 你实际上需要什么,如果有地址作为字符串,你可能不需要它来进行数值分析......
  • 数据库可以帮助访问和加载您实际需要的部分(例如只有 1% 的活跃用户)
于 2014-04-08T21:25:55.163 回答
1

Pandas 0.12.0 和 NumPy 1.8.0 没有错误。

我设法创建了一个大 DataFrame 并将其保存到 csv 文件中,然后成功读取它。请参阅此处的示例。文件大小为 554 Mb(它甚至适用于 1.1 Gb 文件,需要更长的时间,生成 1.1 Gb 文件的使用频率为 30 秒)。虽然我有 4Gb 的 RAM 可用。

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

于 2014-02-04T14:51:37.527 回答
0

添加这些: rating = pd.read_csv(..., low_memory=False, memory_map=True )

我对这两个的记忆:#319.082.496 没有这两个:#349.110.272

于 2020-08-06T13:26:21.213 回答
-1

尽管这是一种解决方法,但与其说是修复不如说是,但我会尝试将 CSV 转换为 JSON(应该很简单)并改用read_json方法 - 我一直在 Pandas 中编写和读取相当大的 JSON/数据帧(100 MB)完全没有任何问题的方式。

于 2014-01-02T09:03:08.090 回答