【问题标题】:Memory error when using pandas read_csv使用 pandas read_csv 时出现内存错误
【发布时间】:2013-07-07 13:58:05
【问题描述】:

我正在尝试做一些相当简单的事情,将一个大的 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 确实对这种大小的文件有问题,我可能会打一场失败的战斗......

【问题讨论】:

  • 当然,熊猫不应该对这种大小的 csvs 有问题。您可以在线发布此文件吗?
  • 您也可以尝试将nrows=something small 传递给read_csv 以确保它不是导致问题的文件的大小,正如安迪所说,不应该是案例。
  • 我找到了以下解决问题的方法:将 csv 读取为块 csv_chunks = pandas.read_csv(filepath, sep = DELIMITER,skiprows = 1, chunksize = 10000),然后连接块 df = pandas.concat(chunk for chunk in csv_chunks)。我仍然很想知道为什么一口气阅读它不起作用,对我来说这看起来像是 csv 阅读器的问题。
  • 如果有人还在关注这个,我有一点更新。我开始相信 csv 解析器很好(而且速度也很快),但是在创建数据帧时存在某种内存问题。我相信这一点的原因:当我使用chunksize=1000 hack 来读取 csv,然后尝试将所有块连接到一个大数据帧中时,内存就会爆炸,相比之下,内存占用大约是 3-4 倍到原始文件的大小。有谁知道为什么数据框可能会爆炸?
  • 其实发现限制是我的问题。现在它正在工作。 fromtxt 对我来说太慢了。现在我遇到了不同的内存不足错误,其中表(合并后)逐渐变大到大约 15M 行。可能需要考虑 memmap 和/或 hdf5

标签: python windows pandas


【解决方案1】:

Windows 内存限制

在 Windows 中使用 32 位版本时,python 经常发生内存错误。这是因为 32 位默认处理 only gets 2GB of memory to play with

降低内存使用率的技巧

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

pandas.read_csv function 采用一个名为 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 读取上述 csv 文件 没有任何 dtype 选项,则年龄将作为字符串存储在内存中,直到 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+" 强制转换为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)

【讨论】:

  • 我可以看到这如何可以加快读取数据的速度,但会减少内存?当然,它不需要在每列存储多个字符串值来猜测数据类型吗?也就是说,除非你有无数列,或者 read_csv 函数正在做一些非常时髦的事情,否则如果内存使用量明显更高,我会感到非常惊讶。
  • @HannesOvrén 在您读取数据的重要部分之前无法猜测数据类型,否则您可能不得不多次更改它,这会增加成本。我认为 pandas 默认情况下会在进行猜测之前读取前一百万行。通过将 dtypes 添加到 csv 加载中,我将基于 pandas 的产品的内存配置文件降低了 50 倍。
  • 嗯,考虑一下,我想确定“3”是浮点数还是整数可能会有问题,除非您在某处也看到“2.5”。感谢您的解释。我不知道这个。
  • 这不是真的。使用 dtype 并且在内存中更昂贵且时间更慢。在 read_csv 中使用 dtype 测试了 6 次。平均值是:...内存没有 dtype:12,121,429.333333334 |具有 dtype 的内存:12,124,160.0 ... 在 13 次测试中,平均值为: ... time no dtypes: 2.0494697460761437 |使用 dtypes 的时间:2.100334332539485 ... 使用了:import os import psutil process = psutil.Process(os.getpid()) print(process.memory_info().rss) ___数据行:来自三个独立数据集的 150 万,cols 90%是对象类型。 *显然float的大小小于字符串类型
  • @nikolaos_mparoutis 不确定您是如何获得这些结果的。也许您想编写自己的答案,因为在您的评论中很难理解什么是代码以及什么是评论。我的答案很老了,也许有些改变了。
【解决方案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位

【讨论】:

  • low_memory=False 应该使用更少的内存是违反直觉的..
【解决方案3】:

我在读取大的 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")

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

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

      你发现的块文件的连接可能确实是一个问题,也许这个操作需要一些副本......但最后这可能会在你目前的情况下拯救你,但如果你的 csv 得到一个再大一点,你可能会再次撞到那堵墙……

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

      您可以尝试几件事:

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

      【讨论】:

        【解决方案6】:

        Pandas 0.12.0 和 NumPy 1.8.0 没有错误。

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

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

            虽然这是一种解决方法,而不是修复,但我会尝试将 CSV 转换为 JSON(应该是微不足道的)并改用 read_json 方法 - 我一直在编写和读取相当大的 JSON/数据帧(100s MB) 以这种方式在 Pandas 中完全没有任何问题。

            【讨论】:

              猜你喜欢
              • 2016-06-02
              • 2021-12-31
              • 1970-01-01
              • 2022-07-25
              • 2017-03-06
              • 2017-05-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多