【问题标题】:Avoiding Memory Issues For GroupBy on Large Pandas DataFrame避免大型 Pandas DataFrame 上 GroupBy 的内存问题
【发布时间】:2018-10-07 15:19:39
【问题描述】:

更新:

pandas df 是这样创建的:

df = pd.read_sql(query, engine)
encoded = pd.get_dummies(df, columns=['account'])

从此 df 创建一个 dask df 如下所示:

df = dd.from_pandas(encoded, 50)

使用 dask 执行操作导致看不到任何进展(使用 dask 诊断检查):

result = df.groupby('journal_entry').max().reset_index().compute()

原文:

我有一个大熊猫 df,它有 270 万行和 4,000 列。除了四列之外,所有列都是 dtype uint8。 uint8 列仅包含 1 或 0 的值。我正在尝试在 df 上执行此操作:

result = df.groupby('id').max().reset_index()

可以预见的是,这个操作会立即返回一个内存错误。我最初的想法是在水平和垂直方向上分块 df。但是,这会造成混乱的情况,因为.max() 需要在所有 uint8 列上执行,而不仅仅是一对列。此外,像这样对 df 进行分块仍然非常慢。我的机器上有 32 GB 的 RAM。

什么策略可以缓解内存问题?

【问题讨论】:

    标签: python pandas dataframe memory dask


    【解决方案1】:

    作为一个想法,我会说,明智地将数据列拆分四次,并使用每个子集的 id 来执行操作,然后重新合并

    【讨论】:

    • 是的,这就是我目前的思路——尽管一次只有两列,但速度非常慢
    【解决方案2】:

    你可以使用dask.dataframe 来完成这个任务

    import dask.dataframe as dd
    df = dd.from_pandas(df)
    result = df.groupby('id').max().reset_index().compute()
    

    您只需将pandas.DataFrame 转换为dask.dataframe。 Dask 是一个 python 核外并行化框架,它提供了各种并行化的容器类型,其中一种是数据帧。它让您可以并行执行最常见的 pandas.DataFrame 操作和/或使用太大而无法放入内存的数据分布。 dask 的核心是一组调度程序和一个用于构建计算图的 API,因此我们必须在最后调用 .compute() 才能真正进行任何计算。该库易于安装,因为它大部分是用纯 Python 编写的。

    【讨论】:

    • 我很久以前读过关于 dask 的文章,但很快就忘记了......到目前为止似乎还在工作。没有内存错误,我的使用量没有攀升。我确实必须添加一个 numpartitions 或 chunksize ...我只是输入了dd.from_pandas(df,1000) - 不确定什么是合适的。任何估计该数据量可能需要多长时间?我应该将 1000 更改为不同的值吗?
    • dask.diagnostics 有一个进度条,它应该是确定计算需要多长时间的完美工具。 Groupby 操作在 dask 中是出了名的慢,因此您可以通过在执行 groupby 之前将 'id' 设置为索引来加快整个操作。
    • 也不确定是否可以在 pandas 中执行 groupby,然后只让 dask 处理其余的计算。 Groupby 和索引操作在 dask 中很慢,因为它必须为每个分区设置索引,然后与其他分区通信(对于 groupby 也是如此)。所以一般来说,如果你有更少的分区,这些操作应该会更快,但不要引用我的话。
    • 非常感谢 - 这都是很棒的信息。当您说“与其他分区通信”时,.max() 函数将跨分区计算,对吗?我无法从文档中看出。再次感谢 - 计划今天早上再试一次。
    • 另外,groupby 不是需要.max() 吗?否则 groupby 将没有任何要分组的内容。
    【解决方案3】:

    如果您的数据中有任何分类列(而不是存储为对象列或字符串的类别),请确保在 groupby 命令中使用 observed=True 选项。这确保它只创建存在条目的行,例如每个 customer_id,order_id 组合只有一行,而不是创建 n_custs * n_orders 行!

    我刚刚对 26M 行数据集进行了 groupby-sum,从未超过 7GB 的 RAM。在添加observed=True 选项之前,它会上升到62GB,然后用完。

    【讨论】:

    • 你救了我的培根!从字面上看,它从几小时到几毫秒!您知道他们不将其设置为默认值的原因吗?
    • 在将 pandas 包版本从 0.23.3 更新到 0.25.1 时,我的内存消耗大幅增加。我假设此标志在早期版本中默认启用。
    猜你喜欢
    • 2017-06-08
    • 2018-11-17
    • 2018-05-06
    • 2018-07-29
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 2013-12-28
    • 2020-06-10
    相关资源
    最近更新 更多