具有许多列的Pandas v 0.25 groupby出现内存错误

dced5bon  于 2023-01-28  发布在  其他
关注(0)|答案(2)|浏览(97)

在更新到panda v0.25.2之后,一个脚本在一个大的 Dataframe 上的许多列上执行groupby操作不再起作用。我得到一个内存错误

MemoryError: Unable to allocate array with shape (some huge number...,) and data type int64

我做了一些研究,发现Git的早期版本报告了问题(#14942

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'cat': np.random.randint(0, 255, size=3000000),
    'int_id': np.random.randint(0, 255, size=3000000),
    'other_id': np.random.randint(0, 10000, size=3000000),
    'foo': 0
}) 
df['cat'] = df.cat.astype(str).astype('category')

# killed after 6 minutes of 100% cpu and  90G maximum main memory usage
grouped = df.groupby(['cat', 'int_id', 'other_id']).count()

运行这段代码(在0.25.2版本上)也会出现内存错误。是我做错了什么(Pandasv0.25中的语法改变了吗?),还是这个标记为已解决的问题又回来了?

9jyewag0

9jyewag01#

使用observed=True来修复它,并防止groupby展开所有可能的因子变量组合:

df.groupby(index, observed=True)

有一个相关的 *GitHub问题 *:PERF: groupby with many empty groups memory blowup .

tcbh2hod

tcbh2hod2#

虽然所提出的解决方案解决了该问题,但是当处理较大的数据集时,可能会出现另一个问题。pandas groupby速度慢并且需要存储器;可能需要5 - 10倍的数据集内存。一个更有效的解决方案是使用一个数量级更快、内存消耗更少并且seamlessly integrates with pandas;它直接从 Dataframe 内存中读取。不需要数据往返,通常也不需要大量的数据分块。
我选择的新的快速数据聚合工具是https://duckdb.org。它直接获取你现有的 Dataframe df并对其进行查询,甚至不需要将其导入数据库。下面是一个使用你的 Dataframe 生成代码的最终结果示例。请注意,总时间是0.45秒。不知道为什么Pandas不使用DuckDB进行幕后的groupby。

db对象是使用这个小 Package 器类创建的,您只需键入db = DuckDB(),就可以浏览任何项目中的数据。您可以进一步扩展它,甚至可以使用% sql简化它。在这里输入链接描述。2顺便说一句,sql返回一个 Dataframe ,所以你也可以做db. sql(...). pivot_table(...)就是这么简单。

class DuckDB:
  def __init__(self, db=None):
      self.db_loc = db or ':memory:'
      self.db = duckdb.connect(self.db_loc)
  def sql(self, sql=""):
     return self.db.execute(sql).fetchdf()
  def __del__():
     self.db.close()

注:DuckDB很好但并不完美,但它比Dusk甚至PySpark更稳定,设置也更简单。对于更大的数据集,您可能需要一个真正的数据库,但对于可以容纳在内存中的数据集,这是很好的。关于内存使用,如果您有一个更大数据集,请确保使用杂注限制DuckDB,因为它会立即将其全部吃掉。限制只是将额外的数据放到磁盘上,而不处理数据分块。也不要假设这是一个数据库。假设这是内存中的数据库,如果你需要存储一些结果,然后将它们导出到 parquet 中,而不是保存数据库。因为不同版本之间的格式不稳定,所以无论如何都必须导出到parquet才能从一个版本移动到下一个版本。
我把这个数据框扩展到3亿条记录,所以总共有大约12亿条记录或大约9GB。它仍然完成了你的groupby和其他总结统计在32GB的机器上18GB仍然是免费的。

相关问题