避免大型 Pandas DataFrame 上 GroupBy 的内存问题
Avoiding Memory Issues For GroupBy on Large Pandas DataFrame
更新:
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()
原文:
我有一个很大的 pandas df,有 270 万行和 4,000 列。除了四列之外,所有列都是 dtype uint8。 uint8 列仅包含 1 或 0 的值。我正在尝试对 df:
执行此操作
result = df.groupby('id').max().reset_index()
不出所料,这个操作马上returns一个内存错误。我最初的想法是水平和垂直分块 df。但是,这会造成混乱,因为 .max()
需要在所有 uint8 列上执行,而不仅仅是一对列。此外,像这样分块 df 仍然非常慢。我的机器上有 32 GB 的 RAM。
什么策略可以缓解内存问题?
作为一个想法,我想说的是,将数据列明智地拆分四次,并使用每个子集的 id 来执行操作,然后重新合并
您可以使用 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 操作 and/or 分发的数据太大而无法放入内存。 dask 的核心是一组调度程序和一个用于构建计算图的 API,因此我们必须在最后调用 .compute() 才能真正进行任何计算。该库很容易安装,因为它大部分是用纯 python 编写的。
如果您的数据中有任何分类列(而不是存储为对象列或字符串的类别),请确保在 groupby 命令中使用 observed=True 选项。这确保它只创建存在条目的行,例如每个 customer_id、order_id 组合只有一行,而不是创建 n_custs * n_orders 行!
我刚刚在一个 26M 行的数据集上做了一个 groupby-sum,从未超过 7GB 的 RAM。在添加 observed=True 选项之前,它会上升到 62GB,然后 运行 出来。
更新:
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()
原文:
我有一个很大的 pandas df,有 270 万行和 4,000 列。除了四列之外,所有列都是 dtype uint8。 uint8 列仅包含 1 或 0 的值。我正在尝试对 df:
执行此操作result = df.groupby('id').max().reset_index()
不出所料,这个操作马上returns一个内存错误。我最初的想法是水平和垂直分块 df。但是,这会造成混乱,因为 .max()
需要在所有 uint8 列上执行,而不仅仅是一对列。此外,像这样分块 df 仍然非常慢。我的机器上有 32 GB 的 RAM。
什么策略可以缓解内存问题?
作为一个想法,我想说的是,将数据列明智地拆分四次,并使用每个子集的 id 来执行操作,然后重新合并
您可以使用 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 操作 and/or 分发的数据太大而无法放入内存。 dask 的核心是一组调度程序和一个用于构建计算图的 API,因此我们必须在最后调用 .compute() 才能真正进行任何计算。该库很容易安装,因为它大部分是用纯 python 编写的。
如果您的数据中有任何分类列(而不是存储为对象列或字符串的类别),请确保在 groupby 命令中使用 observed=True 选项。这确保它只创建存在条目的行,例如每个 customer_id、order_id 组合只有一行,而不是创建 n_custs * n_orders 行!
我刚刚在一个 26M 行的数据集上做了一个 groupby-sum,从未超过 7GB 的 RAM。在添加 observed=True 选项之前,它会上升到 62GB,然后 运行 出来。